Skip to content

Commit

Permalink
MNT Add tests for using GridField with arbitrary data
Browse files Browse the repository at this point in the history
Note that the main tests are added as behat tests in the admin module
  • Loading branch information
GuySartorelli committed Dec 18, 2023
1 parent 2cafba2 commit 7073246
Show file tree
Hide file tree
Showing 15 changed files with 902 additions and 14 deletions.
114 changes: 114 additions & 0 deletions tests/php/Forms/GridField/GridFieldAddExistingAutocompleterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace SilverStripe\Forms\Tests\GridField;

use LogicException;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Core\Convert;
use SilverStripe\Dev\CSSContentParser;
Expand All @@ -17,6 +18,7 @@
use SilverStripe\Forms\Tests\GridField\GridFieldTest\Stadium;
use SilverStripe\Forms\Tests\GridField\GridFieldTest\Team;
use SilverStripe\ORM\ArrayList;
use SilverStripe\View\ArrayData;

class GridFieldAddExistingAutocompleterTest extends FunctionalTest
{
Expand Down Expand Up @@ -167,6 +169,118 @@ function ($item) {
);
}

public function testGetHTMLFragmentsNeedsDataObject()
{
$component = new GridFieldAddExistingAutocompleter();
$gridField = $this->getGridFieldForComponent($component);
$list = new ArrayList();
$dataClass = ArrayData::class;
$list->setDataClass($dataClass);
$gridField->setList($list);

$this->expectException(LogicException::class);
$this->expectExceptionMessage(
GridFieldAddExistingAutocompleter::class
. " must be used with DataObject subclasses. Found '$dataClass'"
);
// Calling the method will throw an exception.
$component->getHTMLFragments($gridField);
}

public function testGetManipulatedDataNeedsDataObject()
{
$component = new GridFieldAddExistingAutocompleter();
$gridField = $this->getGridFieldForComponent($component);
$list = new ArrayList();
$dataClass = ArrayData::class;
$list->setDataClass($dataClass);
$gridField->setList($list);

$this->expectException(LogicException::class);
$this->expectExceptionMessage(
GridFieldAddExistingAutocompleter::class
. " must be used with DataObject subclasses. Found '$dataClass'"
);

// Calling the method will throw an exception.
$component->getManipulatedData($gridField, $list);
}

public function testDoSearchNeedsDataObject()
{
$component = new GridFieldAddExistingAutocompleter();
$gridField = $this->getGridFieldForComponent($component);
$list = new ArrayList();
$dataClass = ArrayData::class;
$list->setDataClass($dataClass);
$gridField->setList($list);

$this->expectException(LogicException::class);
$this->expectExceptionMessage(
GridFieldAddExistingAutocompleter::class
. " must be used with DataObject subclasses. Found '$dataClass'"
);

// Calling the method will throw an exception.
$component->doSearch($gridField, new HTTPRequest('GET', ''));
}

public function testScaffoldSearchFieldsNeedsDataObject()
{
$component = new GridFieldAddExistingAutocompleter();
$gridField = $this->getGridFieldForComponent($component);
$list = new ArrayList();
$dataClass = ArrayData::class;
$list->setDataClass($dataClass);
$gridField->setList($list);

$this->expectException(LogicException::class);
$this->expectExceptionMessage(
GridFieldAddExistingAutocompleter::class
. " must be used with DataObject subclasses. Found '$dataClass'"
);

// Calling the method will either throw an exception or not.
// The test pass/failure is explicitly about whether an exception is thrown.
$component->scaffoldSearchFields($dataClass);
}

public function testGetPlaceholderTextNeedsDataObject()
{
$component = new GridFieldAddExistingAutocompleter();
$gridField = $this->getGridFieldForComponent($component);
$list = new ArrayList();
$dataClass = ArrayData::class;
$list->setDataClass($dataClass);
$gridField->setList($list);

$this->expectException(LogicException::class);
$this->expectExceptionMessage(
GridFieldAddExistingAutocompleter::class
. " must be used with DataObject subclasses. Found '$dataClass'"
);

// Calling the method will either throw an exception or not.
// The test pass/failure is explicitly about whether an exception is thrown.
$component->getPlaceholderText($dataClass);
}

public function testSetPlaceholderTextDoesntNeedDataObject()
{
$component = new GridFieldAddExistingAutocompleter();
$gridField = $this->getGridFieldForComponent($component);
$list = new ArrayList();
$dataClass = ArrayData::class;
$list->setDataClass($dataClass);
$gridField->setList($list);

// Prevent from being marked risky.
// This test passes if there's no exception thrown.
$this->expectNotToPerformAssertions();

$component->setPlaceholderText('');
}

protected function getGridFieldForComponent($component)
{
$config = GridFieldConfig::create()->addComponents(
Expand Down
22 changes: 22 additions & 0 deletions tests/php/Forms/GridField/GridFieldAddNewButtonTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@

namespace SilverStripe\Forms\Tests\GridField;

use LogicException;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldAddNewButton;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldConfig_Base;
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\Person;
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\PeopleGroup;
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\Category;
use SilverStripe\Forms\Tests\GridField\GridFieldDetailFormTest\TestController;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\SS_List;
use SilverStripe\View\ArrayData;

class GridFieldAddNewButtonTest extends SapphireTest
{
Expand Down Expand Up @@ -76,6 +80,24 @@ public function testButtonPassesNoParentContextToSingletonWhenNoParentRecordExis
$this->mockButtonFragments($list, null);
}

public function testGetHTMLFragmentsThrowsException()
{
$component = new GridFieldAddNewButton();
$config = new GridFieldConfig_Base();
$config->addComponent($component);
$gridField = new GridField('dummy', 'dummy', new ArrayList(), $config);
$modelClass = ArrayData::class;
$gridField->setModelClass($modelClass);

$this->expectException(LogicException::class);
$this->expectExceptionMessage(
GridFieldAddNewButton::class . ' cannot be used with models that do not implement canCreate().'
. " Remove this component from your GridField or implement canCreate() on $modelClass"
);

$component->getHTMLFragments($gridField);
}

protected function mockButtonFragments(SS_List $list, $parent = null)
{
$form = Form::create(
Expand Down
36 changes: 35 additions & 1 deletion tests/php/Forms/GridField/GridFieldDataColumnsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
namespace SilverStripe\Forms\Tests\GridField;

use InvalidArgumentException;
use LogicException;
use SilverStripe\Forms\GridField\GridFieldDataColumns;
use SilverStripe\Security\Member;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig_Base;
use SilverStripe\ORM\ArrayList;
use SilverStripe\View\ArrayData;
use stdClass;

class GridFieldDataColumnsTest extends SapphireTest
{

/**
* @covers \SilverStripe\Forms\GridField\GridFieldDataColumns::getDisplayFields
*/
Expand All @@ -23,6 +26,19 @@ public function testGridFieldGetDefaultDisplayFields()
$this->assertEquals($expected, $columns->getDisplayFields($obj));
}

/**
* @covers \SilverStripe\Forms\GridField\GridFieldDataColumns::getDisplayFields
*/
public function testGridFieldGetDisplayFieldsWithArrayList()
{
$list = new ArrayList([new ArrayData(['Title' => 'My Item'])]);
$obj = new GridField('testfield', 'testfield', $list);
$expected = ['Title' => 'Title'];
$columns = $obj->getConfig()->getComponentByType(GridFieldDataColumns::class);
$columns->setDisplayFields($expected);
$this->assertEquals($expected, $columns->getDisplayFields($obj));
}

/**
* @covers \SilverStripe\Forms\GridField\GridFieldDataColumns::setDisplayFields
* @covers \SilverStripe\Forms\GridField\GridFieldDataColumns::getDisplayFields
Expand Down Expand Up @@ -76,4 +92,22 @@ public function testFieldFormatting()
$columns->getFieldFormatting()
);
}

public function testGetDisplayFieldsThrowsException()
{
$component = new GridFieldDataColumns();
$config = new GridFieldConfig_Base();
$config->addComponent($component);
$gridField = new GridField('dummy', 'dummy', new ArrayList(), $config);
$modelClass = ArrayData::class;
$gridField->setModelClass($modelClass);

$this->expectException(LogicException::class);
$this->expectExceptionMessage(
'Cannot dynamically determine columns. Pass the column names to setDisplayFields()'
. " or implement a summaryFields() method on $modelClass"
);

$component->getDisplayFields($gridField);
}
}
70 changes: 70 additions & 0 deletions tests/php/Forms/GridField/GridFieldDeleteActionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace SilverStripe\Forms\Tests\GridField;

use LogicException;
use ReflectionMethod;
use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse_Exception;
Expand All @@ -12,6 +14,7 @@
use SilverStripe\Forms\Form;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig;
use SilverStripe\Forms\GridField\GridFieldConfig_Base;
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
use SilverStripe\Forms\Tests\GridField\GridFieldTest\Cheerleader;
use SilverStripe\Forms\Tests\GridField\GridFieldTest\Permissions;
Expand All @@ -22,6 +25,7 @@
use SilverStripe\ORM\ValidationException;
use SilverStripe\Security\Security;
use SilverStripe\Security\SecurityToken;
use SilverStripe\View\ArrayData;

class GridFieldDeleteActionTest extends SapphireTest
{
Expand Down Expand Up @@ -230,4 +234,70 @@ public function testMenuGroup()
$group = $action->getGroup($gridField, $this->list->first(), 'dummy');
$this->assertNull($group, 'A menu group does not exist when the user cannot delete');
}

public function provideHandleActionThrowsException()
{
return [
'unlinks relation' => [true],
'deletes related record' => [false],
];
}

/**
* @dataProvider provideHandleActionThrowsException
*/
public function testHandleActionThrowsException(bool $unlinkRelation)
{
$component = new GridFieldDeleteAction();
$config = new GridFieldConfig_Base();
$config->addComponent($component);
$gridField = new GridField('dummy', 'dummy', new ArrayList([new ArrayData(['ID' => 1])]), $config);
$modelClass = ArrayData::class;
$gridField->setModelClass($modelClass);

$this->expectException(LogicException::class);
$permissionMethod = $unlinkRelation ? 'canEdit' : 'canDelete';
$this->expectExceptionMessage(
GridFieldDeleteAction::class . " cannot be used with models that don't implement {$permissionMethod}()."
. " Remove this component from your GridField or implement {$permissionMethod}() on $modelClass"
);

// Calling the method will throw an exception.
$secondArg = $unlinkRelation ? 'unlinkrelation' : 'deleterecord';
$component->handleAction($gridField, $secondArg, ['RecordID' => 1], []);
}

public function provideGetRemoveActionThrowsException()
{
return [
'removes relation' => [true],
'deletes related record' => [false],
];
}

/**
* @dataProvider provideGetRemoveActionThrowsException
*/
public function testGetRemoveActionThrowsException(bool $removeRelation)
{
$component = new GridFieldDeleteAction();
$component->setRemoveRelation($removeRelation);
$config = new GridFieldConfig_Base();
$config->addComponent($component);
$gridField = new GridField('dummy', 'dummy', new ArrayList([new ArrayData(['ID' => 1])]), $config);
$modelClass = ArrayData::class;
$gridField->setModelClass($modelClass);

$this->expectException(LogicException::class);
$permissionMethod = $removeRelation ? 'canEdit' : 'canDelete';
$this->expectExceptionMessage(
GridFieldDeleteAction::class . " cannot be used with models that don't implement {$permissionMethod}()."
. " Remove this component from your GridField or implement {$permissionMethod}() on $modelClass"
);

// Calling the method will throw an exception.
$reflectionMethod = new ReflectionMethod($component, 'getRemoveAction');
$reflectionMethod->setAccessible(true);
$reflectionMethod->invokeArgs($component, [$gridField, new ArrayData(), '']);
}
}
Loading

0 comments on commit 7073246

Please sign in to comment.