Source of file DataObjectScaffolderTest.php
Size: 18,550 Bytes - Last Modified: 2021-12-23T10:31:47+00:00
/var/www/docs.ssmods.com/process/src/tests/Scaffolding/Scaffolders/DataObjectScaffolderTest.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 | <?php namespace SilverStripe\GraphQL\Tests\Scaffolders\Scaffolding; use Exception; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ResolveInfo; use InvalidArgumentException; use SilverStripe\Core\Config\Config; use SilverStripe\Dev\SapphireTest; use SilverStripe\GraphQL\Manager; use SilverStripe\GraphQL\Scaffolding\Extensions\TypeCreatorExtension; use SilverStripe\GraphQL\Scaffolding\Scaffolders\CRUD\Create; use SilverStripe\GraphQL\Scaffolding\Scaffolders\CRUD\Delete; use SilverStripe\GraphQL\Scaffolding\Scaffolders\CRUD\Read; use SilverStripe\GraphQL\Scaffolding\Scaffolders\CRUD\Update; use SilverStripe\GraphQL\Scaffolding\Scaffolders\DataObjectScaffolder; use SilverStripe\GraphQL\Scaffolding\Scaffolders\OperationScaffolder; use SilverStripe\GraphQL\Scaffolding\Scaffolders\QueryScaffolder; use SilverStripe\GraphQL\Scaffolding\Scaffolders\SchemaScaffolder; use SilverStripe\GraphQL\Scaffolding\StaticSchema; use SilverStripe\GraphQL\Tests\Fake\DataObjectFake; use SilverStripe\GraphQL\Tests\Fake\FakeFieldAccessor; use SilverStripe\GraphQL\Tests\Fake\FakePage; use SilverStripe\GraphQL\Tests\Fake\FakeRedirectorPage; use SilverStripe\GraphQL\Tests\Fake\FakeSiteTree; use SilverStripe\ORM\FieldType\DBInt; class DataObjectScaffolderTest extends SapphireTest { protected function setUp(): void { parent::setUp(); foreach (Read::get_extensions() as $class) { Read::remove_extension($class); } } public function testDataObjectScaffolderConstructor() { $scaffolder = $this->getFakeScaffolder(); $this->assertEquals(DataObjectFake::class, $scaffolder->getDataObjectClass()); $this->assertInstanceOf(DataObjectFake::class, $scaffolder->getDataObjectInstance()); $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessageMatches('/Non-existent classname/i'); new DataObjectScaffolder('fail'); } public function testDataObjectScaffolderFields() { $scaffolder = $this->getFakeScaffolder(); $scaffolder->addField('MyField'); $this->assertEquals(['MyField'], $scaffolder->getFields()->column('Name')); $scaffolder->addField('MyField', 'Some description'); $this->assertEquals( 'Some description', $scaffolder->getFieldDescription('MyField') ); $scaffolder->addFields([ 'MyField', 'MyInt' => 'Int description', ]); $this->assertEquals(['MyField', 'MyInt'], $scaffolder->getFields()->column('Name')); $this->assertNull( $scaffolder->getFieldDescription('MyField') ); $this->assertEquals( 'Int description', $scaffolder->getFieldDescription('MyInt') ); $scaffolder->setFieldDescription('MyInt', 'New int description'); $this->assertEquals( 'New int description', $scaffolder->getFieldDescription('MyInt') ); $scaffolder = $this->getFakeScaffolder(); $scaffolder->addAllFields(); $this->assertEquals( ['ID', 'ClassName', 'LastEdited', 'Created', 'MyField', 'MyInt'], $scaffolder->getFields()->column('Name') ); $scaffolder = $this->getFakeScaffolder(); $scaffolder->addAllFields(true); $this->assertEquals( ['ID', 'ClassName', 'LastEdited', 'Created', 'MyField', 'MyInt', 'Author'], $scaffolder->getFields()->column('Name') ); $scaffolder = $this->getFakeScaffolder(); $scaffolder->addAllFieldsExcept('MyInt'); $this->assertEquals( ['ID', 'ClassName', 'LastEdited', 'Created', 'MyField'], $scaffolder->getFields()->column('Name') ); $scaffolder = $this->getFakeScaffolder(); $scaffolder->addAllFieldsExcept('MyInt', true); $this->assertEquals( ['ID', 'ClassName', 'LastEdited', 'Created', 'MyField', 'Author'], $scaffolder->getFields()->column('Name') ); $scaffolder->removeField('ClassName'); $this->assertEquals( ['ID', 'LastEdited', 'Created', 'MyField', 'Author'], $scaffolder->getFields()->column('Name') ); $scaffolder->removeFields(['LastEdited', 'Created']); $this->assertEquals( ['ID', 'MyField', 'Author'], $scaffolder->getFields()->column('Name') ); } public function testDataObjectScaffolderOperations() { $scaffolder = $this->getFakeScaffolder(); $op = $scaffolder->operation(SchemaScaffolder::CREATE); $this->assertInstanceOf(OperationScaffolder::class, $op); // Ensure we get back the same reference $op->Test = true; $op = $scaffolder->operation(SchemaScaffolder::CREATE); $this->assertEquals(true, $op->Test); // Ensure duplicates aren't created $scaffolder->operation(SchemaScaffolder::DELETE); $this->assertEquals(2, $scaffolder->getOperations()->count()); $scaffolder->removeOperation(SchemaScaffolder::DELETE); $this->assertEquals(1, $scaffolder->getOperations()->count()); $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessageMatches('/Invalid operation/'); $scaffolder = $this->getFakeScaffolder(); $scaffolder->operation('fail'); } public function testDataObjectScaffolderNestedQueries() { $scaffolder = $this->getFakeScaffolder(); $query = $scaffolder->nestedQuery('Files'); $this->assertInstanceOf(QueryScaffolder::class, $query); // Ensure we get back the same reference $query->Test = true; $query = $scaffolder->nestedQuery('Files'); $this->assertEquals(true, $query->Test); // Ensure duplicates aren't created $this->assertCount(1, $scaffolder->getNestedQueries()); // Ensure nested queries are not added to manager $managerMock = $this->getMockBuilder(Manager::class) ->setMethods(['addQuery']) ->getMock(); $managerMock ->expects($this->never()) ->method('addQuery'); $managerMock->addType(new ObjectType([ 'name' => 'File', 'fields' => [] ])); $scaffolder->addToManager($managerMock); // Can't add a nested query for a regular field $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessageMatches('/returns a DataList or ArrayList/'); $scaffolder = $this->getFakeScaffolder(); $scaffolder->nestedQuery('MyField'); } public function testDataObjectScaffolderDependentClasses() { $scaffolder = $this->getFakeScaffolder(); $this->assertEquals([], $scaffolder->getDependentClasses()); $scaffolder->nestedQuery('Files'); $this->assertEquals( [$scaffolder->getDataObjectInstance()->Files()->dataClass()], $scaffolder->getDependentClasses() ); $scaffolder->addField('Author'); $this->assertEquals( [ get_class($scaffolder->getDataObjectInstance()->Author()), $scaffolder->getDataObjectInstance()->Files()->dataClass(), ], $scaffolder->getDependentClasses() ); } public function testDataObjectScaffolderAncestralClasses() { $scaffolder = new DataObjectScaffolder(FakeRedirectorPage::class); $classes = $scaffolder->getAncestralClasses(); $this->assertEquals([ FakePage::class, FakeSiteTree::class, ], $classes); } public function testDataObjectScaffolderApplyConfig() { /** @var DataObjectScaffolder $observer */ $observer = $this->getMockBuilder(DataObjectScaffolder::class) ->setConstructorArgs([DataObjectFake::class]) ->setMethods(['addFields', 'removeFields', 'operation', 'nestedQuery', 'setFieldDescription']) ->getMock(); $observer->expects($this->once()) ->method('addFields') ->with($this->equalTo(['ID', 'MyField', 'MyInt'])); $observer->expects($this->once()) ->method('removeFields') ->with($this->equalTo(['ID'])); $observer->expects($this->exactly(2)) ->method('operation') ->withConsecutive( [$this->equalTo(SchemaScaffolder::CREATE)], [$this->equalTo(SchemaScaffolder::READ)] ) ->will($this->returnValue( $this->getMockBuilder(Create::class) ->disableOriginalConstructor() ->getMock() )); $observer->expects($this->once()) ->method('nestedQuery') ->with($this->equalTo('Files')) ->will($this->returnValue( $this->getMockBuilder(QueryScaffolder::class) ->disableOriginalConstructor() ->getMock() )); $observer->expects($this->once()) ->method('setFieldDescription') ->with( $this->equalTo('MyField'), $this->equalTo('This is myfield') ); $observer->applyConfig([ 'fields' => ['ID', 'MyField', 'MyInt'], 'excludeFields' => ['ID'], 'operations' => ['create' => true, 'read' => true], 'nestedQueries' => ['Files' => true], 'fieldDescriptions' => [ 'MyField' => 'This is myfield', ], ]); } public function testDataObjectScaffolderApplyConfigNoFieldsException() { $scaffolder = $this->getFakeScaffolder(); // Must have "fields" defined $this->expectException(Exception::class); $this->expectExceptionMessageMatches('/^No fields or nestedQueries/'); $scaffolder->applyConfig([ 'operations' => ['create' => true], ]); } public function testDataObjectScaffolderApplyConfigInvalidFieldsException() { $scaffolder = $this->getFakeScaffolder(); // Invalid fields $this->expectException(Exception::class); $this->expectExceptionMessageMatches('/Fields must be an array/'); $scaffolder->applyConfig([ 'fields' => 'fail', ]); } public function testDataObjectScaffolderApplyConfigInvalidFieldsExceptException() { $scaffolder = $this->getFakeScaffolder(); // Invalid fieldsExcept $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessageMatches('/"excludeFields" must be an enumerated list/'); $scaffolder->applyConfig([ 'fields' => ['MyField'], 'excludeFields' => 'fail', ]); } public function testDataObjectScaffolderApplyConfigInvalidOperationsException() { $scaffolder = $this->getFakeScaffolder(); // Invalid operations $this->expectException(Exception::class); $this->expectExceptionMessageMatches('/Operations field must be a map/'); $scaffolder->applyConfig([ 'fields' => ['MyField'], 'operations' => ['create'], ]); } public function testDataObjectScaffolderApplyConfigInvalidNestedQueriesException() { $scaffolder = $this->getFakeScaffolder(); // Invalid nested queries $this->expectException(Exception::class); $this->expectExceptionMessageMatches('/"nestedQueries" must be a map of relation name/'); $scaffolder->applyConfig([ 'fields' => ['MyField'], 'nestedQueries' => ['Files'], ]); } public function testDataObjectScaffolderWildcards() { $scaffolder = $this->getFakeScaffolder(); $scaffolder->applyConfig([ 'fields' => SchemaScaffolder::ALL, 'operations' => SchemaScaffolder::ALL, ]); $ops = $scaffolder->getOperations(); $this->assertInstanceOf(Create::class, $ops->findByIdentifier(SchemaScaffolder::CREATE)); $this->assertInstanceOf(Delete::class, $ops->findByIdentifier(SchemaScaffolder::DELETE)); $this->assertInstanceOf(Read::class, $ops->findByIdentifier(SchemaScaffolder::READ)); $this->assertInstanceOf(Update::class, $ops->findByIdentifier(SchemaScaffolder::UPDATE)); $this->assertEquals( ['ID', 'ClassName', 'LastEdited', 'Created', 'MyField', 'MyInt', 'Author'], $scaffolder->getFields()->column('Name') ); } public function testDataObjectScaffolderScaffold() { $manager = $this->getMockBuilder(Manager::class) ->setMethods(['getType', 'hasType']) ->getMock(); $manager->method('getType') ->will($this->returnValue([])); $manager->method('hasType') ->will($this->returnValue(true)); $scaffolder = $this->getFakeScaffolder(); $scaffolder->addFields(['MyField', 'Author']) ->nestedQuery('Files'); $objectType = $scaffolder->scaffold($manager); $this->assertInstanceof(ObjectType::class, $objectType); $config = $objectType->config; $this->assertEquals($scaffolder->getTypeName(), $config['name']); $this->assertEquals(['MyField', 'Author', 'Files'], array_keys($config['fields']())); } public function testDataObjectScaffolderScaffoldFieldException() { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessageMatches('/Invalid field/'); $scaffolder = $this->getFakeScaffolder() ->addFields(['not a field']) ->scaffold(new Manager()); $scaffolder->config['fields'](); } public function testDataObjectScaffolderScaffoldNestedQueryException() { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessageMatches('/returns a list/'); $scaffolder = $this->getFakeScaffolder() ->addFields(['Files']) ->scaffold(new Manager()); $scaffolder->config['fields'](); } public function testDataObjectScaffolderAddToManager() { $manager = new Manager(); /** @var DataObjectScaffolder $scaffolder */ $scaffolder = $this->getFakeScaffolder() ->addFields(['MyField']) ->operation(SchemaScaffolder::CREATE) ->setName('Create and Barrel') ->end() ->operation(SchemaScaffolder::READ) ->setName('Ready McRead') ->end(); $scaffolder->addToManager($manager); $schema = $manager->schema(); $queryConfig = $schema->getQueryType()->config; $mutationConfig = $schema->getMutationType()->config; $this->assertArrayHasKey( 'Ready McRead', $queryConfig['fields']() ); $this->assertArrayHasKey( 'Create and Barrel', $mutationConfig['fields']() ); $this->assertTrue($manager->hasType($scaffolder->getTypeName())); } public function testDataObjectScaffolderSimpleFieldTypes() { $scaffolder = $this->getFakeScaffolder(); $scaffolder->addField('MyInt'); $manager = new Manager(); $result = $scaffolder->scaffold($manager); $fields = $result->config['fields'](); $myIntResolver = $fields['MyInt']['resolve']; $fake = new DataObjectFake(['MyInt' => 5]); $value = $myIntResolver($fake, [], null, new ResolveInfo(['fieldName' => 'MyInt'])); $this->assertEquals(5, $value); Config::modify()->merge(DBInt::class, 'graphql_type', [ 'FieldOne' => 'String', 'FieldTwo' => 'Int', ]); } public function testDataObjectScaffolderComplexFieldTypes() { Config::modify()->merge(DBInt::class, 'graphql_type', [ 'FieldOne' => 'String', 'FieldTwo' => 'Int', ]); $fake = new DataObjectFake(['MyInt' => 5]); $manager = new Manager(); /** @var DBInt|TypeCreatorExtension $dbInt */ $dbInt = new DBInt(0); $dbInt->addToManager($manager); $this->assertInstanceOf(ObjectType::class, $fake->obj('MyInt')->getGraphQLType($manager)); $scaffolder = $this->getFakeScaffolder(); $scaffolder->addField('MyInt'); $result = $scaffolder->scaffold($manager); $fields = $result->config['fields'](); $myIntResolver = $fields['MyInt']['resolve']; $value = $myIntResolver($fake, [], null, new ResolveInfo(['fieldName' => 'MyInt'])); $this->assertInstanceOf(DBInt::class, $value); } public function testCloneTo() { $scaffolder = new DataObjectScaffolder(FakeRedirectorPage::class); $scaffolder->addFields(['Title', 'RedirectionType', 'ID']); $scaffolder->operation(SchemaScaffolder::READ); $scaffolder->operation(SchemaScaffolder::UPDATE); $target = new DataObjectScaffolder(FakeSiteTree::class); $this->assertNotContains('Title', $target->getFields()->column('Name')); $this->assertNotContains('RedirectionType', $target->getFields()->column('Name')); $this->assertEmpty($target->getOperations()); $target = $scaffolder->cloneTo($target); $this->assertContains('Title', $target->getFields()->column('Name')); $this->assertNotContains('RedirectionType', $target->getFields()->column('Name')); $this->assertCount(2, $target->getOperations()); } public function testFieldAccessor() { StaticSchema::inst()->setFieldAccessor(new FakeFieldAccessor()); $scaffolder = $this->getFakeScaffolder() ->addField('dleiFyM') ->addField('MyField'); $type = $scaffolder->scaffold(new Manager()); $fields = $type->config['fields'](); $this->assertArrayHasKey('dleiFyM', $fields); $this->assertArrayHasKey('MyField', $fields); $this->assertArrayNotHasKey('myfeild', $fields); StaticSchema::reset(); } /** * @return DataObjectScaffolder */ protected function getFakeScaffolder() { return new DataObjectScaffolder(DataObjectFake::class); } } |