2015-05-15 12:29:17 +02:00
|
|
|
<?php
|
|
|
|
|
2017-06-22 07:15:17 +02:00
|
|
|
namespace SilverStripe\TagField\Tests;
|
|
|
|
|
2018-11-16 10:29:49 +01:00
|
|
|
use PHPUnit_Framework_TestCase;
|
2017-01-13 20:11:59 +01:00
|
|
|
use SilverStripe\Control\HTTPRequest;
|
|
|
|
use SilverStripe\Dev\SapphireTest;
|
|
|
|
use SilverStripe\Forms\FieldList;
|
|
|
|
use SilverStripe\Forms\Form;
|
|
|
|
use SilverStripe\ORM\DataList;
|
|
|
|
use SilverStripe\ORM\DataObject;
|
2018-01-19 08:37:55 +01:00
|
|
|
use SilverStripe\TagField\ReadonlyTagField;
|
2017-01-13 20:11:59 +01:00
|
|
|
use SilverStripe\TagField\TagField;
|
2017-06-22 07:15:17 +02:00
|
|
|
use SilverStripe\TagField\Tests\Stub\TagFieldTestBlogPost;
|
|
|
|
use SilverStripe\TagField\Tests\Stub\TagFieldTestBlogTag;
|
|
|
|
use SilverStripe\TagField\Tests\Stub\TagFieldTestController;
|
2017-01-13 20:11:59 +01:00
|
|
|
|
2015-05-15 12:29:17 +02:00
|
|
|
/**
|
|
|
|
* @mixin PHPUnit_Framework_TestCase
|
|
|
|
*/
|
2015-11-18 05:05:38 +01:00
|
|
|
class TagFieldTest extends SapphireTest
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var string
|
|
|
|
*/
|
2017-06-22 07:15:17 +02:00
|
|
|
protected static $fixture_file = 'TagFieldTest.yml';
|
2015-11-18 05:05:38 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array
|
|
|
|
*/
|
2017-06-22 07:15:17 +02:00
|
|
|
protected static $extra_dataobjects = [
|
|
|
|
TagFieldTestBlogTag::class,
|
|
|
|
TagFieldTestBlogPost::class,
|
|
|
|
];
|
2015-11-18 05:05:38 +01:00
|
|
|
|
|
|
|
public function testItSavesLinksToNewTagsOnNewRecords()
|
|
|
|
{
|
|
|
|
$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
|
2017-06-22 07:15:17 +02:00
|
|
|
$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
|
2018-11-16 10:29:49 +01:00
|
|
|
$field->setValue(['Tag3', 'Tag4']);
|
2015-11-18 05:05:38 +01:00
|
|
|
$field->saveInto($record);
|
|
|
|
$record->write();
|
|
|
|
$this->compareExpectedAndActualTags(
|
2018-11-16 10:29:49 +01:00
|
|
|
['Tag3', 'Tag4'],
|
2015-11-18 05:05:38 +01:00
|
|
|
$record
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $name
|
|
|
|
*
|
|
|
|
* @return TagFieldTestBlogPost
|
|
|
|
*/
|
|
|
|
protected function getNewTagFieldTestBlogPost($name)
|
|
|
|
{
|
|
|
|
return $this->objFromFixture(
|
2017-06-22 07:15:17 +02:00
|
|
|
TagFieldTestBlogPost::class,
|
2015-11-18 05:05:38 +01:00
|
|
|
$name
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param array $expected
|
|
|
|
* @param TagFieldTestBlogPost $record
|
|
|
|
*/
|
|
|
|
protected function compareExpectedAndActualTags(array $expected, TagFieldTestBlogPost $record)
|
|
|
|
{
|
|
|
|
$this->compareTagLists($expected, $record->Tags());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ensure a source of tags matches the given string tag names
|
|
|
|
*
|
|
|
|
* @param array $expected
|
|
|
|
* @param DataList $actualSource
|
|
|
|
*/
|
|
|
|
protected function compareTagLists(array $expected, DataList $actualSource)
|
|
|
|
{
|
|
|
|
$actual = array_values($actualSource->map('ID', 'Title')->toArray());
|
|
|
|
sort($expected);
|
|
|
|
sort($actual);
|
|
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
$expected,
|
|
|
|
$actual
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testItSavesLinksToNewTagsOnExistingRecords()
|
|
|
|
{
|
|
|
|
$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
|
|
|
|
$record->write();
|
|
|
|
|
2017-06-22 07:15:17 +02:00
|
|
|
$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
|
2018-11-16 10:29:49 +01:00
|
|
|
$field->setValue(['Tag3', 'Tag4']);
|
2015-11-18 05:05:38 +01:00
|
|
|
$field->saveInto($record);
|
|
|
|
|
|
|
|
$this->compareExpectedAndActualTags(
|
|
|
|
array('Tag3', 'Tag4'),
|
|
|
|
$record
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testItSavesLinksToExistingTagsOnNewRecords()
|
|
|
|
{
|
|
|
|
$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
|
|
|
|
|
2017-06-22 07:15:17 +02:00
|
|
|
$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
|
2018-11-16 10:29:49 +01:00
|
|
|
$field->setValue(['Tag1', 'Tag2']);
|
2015-11-18 05:05:38 +01:00
|
|
|
$field->saveInto($record);
|
|
|
|
|
|
|
|
$record->write();
|
|
|
|
|
|
|
|
$this->compareExpectedAndActualTags(
|
2018-11-16 10:29:49 +01:00
|
|
|
['Tag1', 'Tag2'],
|
2015-11-18 05:05:38 +01:00
|
|
|
$record
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testItSavesLinksToExistingTagsOnExistingRecords()
|
|
|
|
{
|
|
|
|
$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
|
|
|
|
$record->write();
|
|
|
|
|
2017-06-22 07:15:17 +02:00
|
|
|
$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
|
2018-11-16 10:29:49 +01:00
|
|
|
$field->setValue(['Tag1', 'Tag2']);
|
2015-11-18 05:05:38 +01:00
|
|
|
$field->saveInto($record);
|
|
|
|
|
|
|
|
$this->compareExpectedAndActualTags(
|
2018-11-16 10:29:49 +01:00
|
|
|
['Tag1', 'Tag2'],
|
2015-11-18 05:05:38 +01:00
|
|
|
$record
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ensure that {@see TagField::saveInto} respects existing tags
|
|
|
|
*/
|
|
|
|
public function testSaveDuplicateTags()
|
|
|
|
{
|
|
|
|
$record = $this->getNewTagFieldTestBlogPost('BlogPost2');
|
|
|
|
$record->write();
|
2017-06-22 07:15:17 +02:00
|
|
|
$tag2ID = $this->idFromFixture(TagFieldTestBlogTag::class, 'Tag2');
|
2015-11-18 05:05:38 +01:00
|
|
|
|
|
|
|
// Check tags before write
|
|
|
|
$this->compareExpectedAndActualTags(
|
2018-11-16 10:29:49 +01:00
|
|
|
['Tag1', '222'],
|
2015-11-18 05:05:38 +01:00
|
|
|
$record
|
|
|
|
);
|
|
|
|
$this->compareTagLists(
|
2018-11-16 10:29:49 +01:00
|
|
|
['Tag1', '222'],
|
2015-11-18 05:05:38 +01:00
|
|
|
TagFieldTestBlogTag::get()
|
|
|
|
);
|
|
|
|
$this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID'));
|
|
|
|
|
|
|
|
// Write new tags
|
2017-06-22 07:15:17 +02:00
|
|
|
$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
|
2018-11-16 10:29:49 +01:00
|
|
|
$field->setValue(['222', 'Tag3']);
|
2015-11-18 05:05:38 +01:00
|
|
|
$field->saveInto($record);
|
|
|
|
|
|
|
|
// Check only one new tag was added
|
|
|
|
$this->compareExpectedAndActualTags(
|
2018-11-16 10:29:49 +01:00
|
|
|
['222', 'Tag3'],
|
2015-11-18 05:05:38 +01:00
|
|
|
$record
|
|
|
|
);
|
|
|
|
|
|
|
|
// Ensure that only one new dataobject was added and that tag2s id has not changed
|
|
|
|
$this->compareTagLists(
|
2018-11-16 10:29:49 +01:00
|
|
|
['Tag1', '222', 'Tag3'],
|
2015-11-18 05:05:38 +01:00
|
|
|
TagFieldTestBlogTag::get()
|
|
|
|
);
|
|
|
|
$this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID'));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testItSuggestsTags()
|
|
|
|
{
|
2017-06-22 07:15:17 +02:00
|
|
|
$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class));
|
2015-11-18 05:05:38 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Partial tag title match.
|
|
|
|
*/
|
2018-11-16 10:29:49 +01:00
|
|
|
$request = $this->getNewRequest(['term' => 'Tag']);
|
2015-11-18 05:05:38 +01:00
|
|
|
|
|
|
|
$this->assertEquals(
|
2019-07-24 05:55:08 +02:00
|
|
|
'{"items":[{"Title":"Tag1","Value":"Tag1"}]}',
|
2015-11-18 05:05:38 +01:00
|
|
|
$field->suggest($request)->getBody()
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Exact tag title match.
|
|
|
|
*/
|
2018-11-16 10:29:49 +01:00
|
|
|
$request = $this->getNewRequest(['term' => '222']);
|
2015-11-18 05:05:38 +01:00
|
|
|
|
|
|
|
$this->assertEquals(
|
2019-07-24 05:55:08 +02:00
|
|
|
'{"items":[{"Title":"222","Value":"222"}]}',
|
2015-11-18 05:05:38 +01:00
|
|
|
$field->suggest($request)->getBody()
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Case-insensitive tag title match.
|
|
|
|
*/
|
2018-11-16 10:29:49 +01:00
|
|
|
$request = $this->getNewRequest(['term' => 'TAG1']);
|
2015-11-18 05:05:38 +01:00
|
|
|
|
|
|
|
$this->assertEquals(
|
2019-07-24 05:55:08 +02:00
|
|
|
'{"items":[{"Title":"Tag1","Value":"Tag1"}]}',
|
2015-11-18 05:05:38 +01:00
|
|
|
$field->suggest($request)->getBody()
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* No tag title match.
|
|
|
|
*/
|
2018-11-16 10:29:49 +01:00
|
|
|
$request = $this->getNewRequest(['term' => 'unknown']);
|
2015-11-18 05:05:38 +01:00
|
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
'{"items":[]}',
|
|
|
|
$field->suggest($request)->getBody()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tests that TagField supports pre-filtered data sources
|
|
|
|
*/
|
|
|
|
public function testRestrictedSuggestions()
|
|
|
|
{
|
|
|
|
$source = TagFieldTestBlogTag::get()->exclude('Title', 'Tag2');
|
|
|
|
$field = new TagField('Tags', '', $source);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Partial tag title match.
|
|
|
|
*/
|
2018-11-16 10:29:49 +01:00
|
|
|
$request = $this->getNewRequest(['term' => 'Tag']);
|
2015-11-18 05:05:38 +01:00
|
|
|
|
|
|
|
$this->assertEquals(
|
2019-07-24 05:55:08 +02:00
|
|
|
'{"items":[{"Title":"Tag1","Value":"Tag1"}]}',
|
2015-11-18 05:05:38 +01:00
|
|
|
$field->suggest($request)->getBody()
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Exact tag title match.
|
|
|
|
*/
|
2018-11-16 10:29:49 +01:00
|
|
|
$request = $this->getNewRequest(['term' => 'Tag1']);
|
2015-11-18 05:05:38 +01:00
|
|
|
|
|
|
|
$this->assertEquals(
|
2019-07-24 05:55:08 +02:00
|
|
|
'{"items":[{"Title":"Tag1","Value":"Tag1"}]}',
|
2015-11-18 05:05:38 +01:00
|
|
|
$field->suggest($request)->getBody()
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Excluded item doesn't appear in matches
|
|
|
|
*/
|
2018-11-16 10:29:49 +01:00
|
|
|
$request = $this->getNewRequest(['term' => 'Tag2']);
|
2015-11-18 05:05:38 +01:00
|
|
|
|
|
|
|
$this->assertEquals(
|
|
|
|
'{"items":[]}',
|
|
|
|
$field->suggest($request)->getBody()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param array $parameters
|
|
|
|
*
|
2017-01-13 20:11:59 +01:00
|
|
|
* @return HTTPRequest
|
2015-11-18 05:05:38 +01:00
|
|
|
*/
|
|
|
|
protected function getNewRequest(array $parameters)
|
|
|
|
{
|
2017-01-13 20:11:59 +01:00
|
|
|
return new HTTPRequest(
|
2015-11-18 05:05:38 +01:00
|
|
|
'get',
|
|
|
|
'TagFieldTestController/TagFieldTestForm/fields/Tags/suggest',
|
|
|
|
$parameters
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testItDisplaysValuesFromRelations()
|
|
|
|
{
|
|
|
|
$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
|
|
|
|
$record->write();
|
|
|
|
|
|
|
|
$form = new Form(
|
2018-11-16 10:29:49 +01:00
|
|
|
new TagFieldTestController(),
|
2015-11-18 05:05:38 +01:00
|
|
|
'Form',
|
|
|
|
new FieldList(
|
2017-06-22 07:15:17 +02:00
|
|
|
$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class))
|
2015-11-18 05:05:38 +01:00
|
|
|
),
|
|
|
|
new FieldList()
|
|
|
|
);
|
|
|
|
|
|
|
|
$form->loadDataFrom(
|
2017-06-22 07:15:17 +02:00
|
|
|
$this->objFromFixture(TagFieldTestBlogPost::class, 'BlogPost2')
|
2015-11-18 05:05:38 +01:00
|
|
|
);
|
|
|
|
|
2016-02-10 20:44:20 +01:00
|
|
|
$ids = TagFieldTestBlogTag::get()->column('Title');
|
2016-01-05 09:49:08 +01:00
|
|
|
|
|
|
|
$this->assertEquals($field->Value(), $ids);
|
2015-11-18 05:05:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testItIgnoresNewTagsIfCannotCreate()
|
|
|
|
{
|
2016-02-10 20:44:20 +01:00
|
|
|
$this->markTestSkipped(
|
2017-01-13 20:11:59 +01:00
|
|
|
'This test has not been updated yet.'
|
2016-02-10 20:44:20 +01:00
|
|
|
);
|
|
|
|
|
2015-11-18 05:05:38 +01:00
|
|
|
$record = new TagFieldTestBlogPost();
|
|
|
|
$record->write();
|
|
|
|
|
|
|
|
$tag = TagFieldTestBlogTag::get()->filter('Title', 'Tag1')->first();
|
|
|
|
|
2018-11-16 10:29:49 +01:00
|
|
|
$field = new TagField('Tags', '', new DataList(TagFieldTestBlogTag::class), [$tag->Title, 'Tag3']);
|
2015-11-18 05:05:38 +01:00
|
|
|
$field->setCanCreate(false);
|
|
|
|
$field->saveInto($record);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var TagFieldTestBlogPost $record
|
|
|
|
*/
|
2017-06-22 07:15:17 +02:00
|
|
|
$record = DataObject::get_by_id(TagFieldTestBlogPost::class, $record->ID);
|
2015-11-18 05:05:38 +01:00
|
|
|
|
|
|
|
$this->compareExpectedAndActualTags(
|
2018-11-16 10:29:49 +01:00
|
|
|
['Tag1'],
|
2015-11-18 05:05:38 +01:00
|
|
|
$record
|
|
|
|
);
|
|
|
|
}
|
2017-01-26 06:10:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Test you can save without a source set
|
|
|
|
*/
|
|
|
|
public function testSaveEmptySource()
|
|
|
|
{
|
|
|
|
$record = new TagFieldTestBlogPost();
|
|
|
|
$record->write();
|
|
|
|
|
|
|
|
// Clear database of tags
|
|
|
|
TagFieldTestBlogTag::get()->removeAll();
|
|
|
|
|
|
|
|
$field = new TagField('Tags', '', TagFieldTestBlogTag::get());
|
|
|
|
$field->setValue(['New Tag']);
|
|
|
|
$field->setCanCreate(true);
|
|
|
|
$field->saveInto($record);
|
|
|
|
|
|
|
|
$tag = TagFieldTestBlogTag::get()->first();
|
|
|
|
$this->assertNotEmpty($tag);
|
|
|
|
$this->assertEquals('New Tag', $tag->Title);
|
|
|
|
$record = TagFieldTestBlogPost::get()->byID($record->ID);
|
|
|
|
$this->assertEquals(
|
|
|
|
$tag->ID,
|
|
|
|
$record->Tags()->first()->ID
|
|
|
|
);
|
|
|
|
}
|
2018-01-19 08:37:55 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Test read only fields are returned
|
|
|
|
*/
|
|
|
|
public function testReadonlyTransformation()
|
|
|
|
{
|
|
|
|
$field = new TagField('Tags', '', TagFieldTestBlogTag::get());
|
|
|
|
$readOnlyField = $field->performReadonlyTransformation();
|
2018-11-16 10:29:49 +01:00
|
|
|
$this->assertInstanceOf(ReadonlyTagField::class, $readOnlyField);
|
2020-06-17 06:40:57 +02:00
|
|
|
|
|
|
|
// Custom title field
|
|
|
|
$field = new TagField('Tags', '', TagFieldTestBlogTag::get());
|
|
|
|
$field->setTitleField('Name');
|
|
|
|
$readOnlyField = $field->performReadonlyTransformation();
|
|
|
|
$this->assertEquals('Name', $readOnlyField->getTitleField());
|
2018-11-16 10:29:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testGetSchemaDataDefaults()
|
|
|
|
{
|
|
|
|
$form = new Form(null, 'Form', new FieldList(), new FieldList());
|
|
|
|
$field = new TagField('TestField', 'Test Field', TagFieldTestBlogTag::get());
|
|
|
|
$field->setForm($form);
|
|
|
|
|
|
|
|
$field
|
|
|
|
->setShouldLazyLoad(false)
|
|
|
|
->setCanCreate(false);
|
|
|
|
|
|
|
|
$schema = $field->getSchemaDataDefaults();
|
|
|
|
$this->assertSame('TestField[]', $schema['name']);
|
|
|
|
$this->assertFalse($schema['lazyLoad']);
|
|
|
|
$this->assertFalse($schema['creatable']);
|
|
|
|
$this->assertEquals([
|
2019-07-24 05:55:08 +02:00
|
|
|
['Title' => 'Tag1', 'Value' => 'Tag1', 'Selected' => false],
|
|
|
|
['Title' => '222', 'Value' => '222', 'Selected' => false],
|
|
|
|
], $schema['options']);
|
|
|
|
|
|
|
|
$field->setValue(['222']);
|
|
|
|
$schema = $field->getSchemaDataDefaults();
|
|
|
|
|
|
|
|
$this->assertEquals([
|
|
|
|
['Title' => 'Tag1', 'Value' => 'Tag1', 'Selected' => false],
|
|
|
|
['Title' => '222', 'Value' => '222', 'Selected' => true],
|
2018-11-16 10:29:49 +01:00
|
|
|
], $schema['options']);
|
|
|
|
|
|
|
|
$field
|
|
|
|
->setShouldLazyLoad(true)
|
|
|
|
->setCanCreate(true);
|
|
|
|
|
|
|
|
$schema = $field->getSchemaDataDefaults();
|
|
|
|
$this->assertTrue($schema['lazyLoad']);
|
|
|
|
$this->assertTrue($schema['creatable']);
|
|
|
|
$this->assertContains('suggest', $schema['optionUrl']);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testSchemaIsAddedToAttributes()
|
|
|
|
{
|
|
|
|
$field = new TagField('TestField');
|
|
|
|
$attributes = $field->getAttributes();
|
|
|
|
$this->assertNotEmpty($attributes['data-schema']);
|
2018-01-19 08:37:55 +01:00
|
|
|
}
|
2015-05-15 12:29:17 +02:00
|
|
|
}
|