Skip to content

Commit

Permalink
MNT Add test cases for SortPlugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Sabina Talipova committed Nov 27, 2023
1 parent 5781c46 commit b2e9018
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 8 deletions.
55 changes: 53 additions & 2 deletions src/Schema/Plugin/SortPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use SilverStripe\GraphQL\Schema\Type\InputType;
use SilverStripe\ORM\Sortable;
use Closure;
use GraphQL\Type\Definition\ResolveInfo;

class SortPlugin implements FieldPlugin, SchemaUpdater
{
Expand Down Expand Up @@ -86,17 +87,67 @@ public function apply(Field $field, Schema $schema, array $config = []): void
public static function sort(array $context): Closure
{
$fieldName = $context['fieldName'];
return function (?Sortable $list, array $args) use ($fieldName) {
return function (?Sortable $list, array $args, array $context, ResolveInfo $info) use ($fieldName) {
if ($list === null) {
return null;
}
$sortArgs = $args[$fieldName] ?? [];
$sortArgs = static::getSortArgs($info, $args, $fieldName);
$list = $list->sort($sortArgs);

return $list;
};
}

private static function getSortArgs(ResolveInfo $info, array $args, string $fieldName): array
{
$sortArgs = [];
$sortOrder = self::getSortOrder($info, $fieldName);

foreach ($sortOrder as $orderName) {
if (!isset($args[$fieldName][$orderName])) {
continue;
}
$sortArgs[$orderName] = $args[$fieldName][$orderName];
unset($args[$fieldName][$orderName]);
}

return array_merge($sortArgs, $args[$fieldName]);
}

/**
* Gets the original order of fields to be sorted based on the query args order.
*
* This is necessary because the underlying GraphQL implementation we're using ignores the
* order of query args, and uses the order that fields are defined in the schema instead.
*/
private static function getSortOrder(ResolveInfo $info, string $fieldName)
{
$relevantNode = $info->fieldDefinition->getName();

// Find the query field node that matches the schema
foreach ($info->fieldNodes as $node) {
if ($node->name->value !== $relevantNode) {
continue;
}

// Find the sort arg
foreach ($node->arguments as $arg) {
if ($arg->name->value !== $fieldName) {
continue;
}

// Get the sort order from the query
$sortOrder = [];
foreach ($arg->value->fields as $field) {
$sortOrder[] = $field->name->value;
}
return $sortOrder;
}
}

return [];
}

/**
* @throws SchemaBuilderException
*/
Expand Down
133 changes: 127 additions & 6 deletions tests/Schema/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -685,14 +685,119 @@ public function provideFilterAndSortOnlyRead(): array
}
}
GRAPHQL,
'expected' => [
["myField" => "test2", "author" => ["firstName" => "tester2"]],
["myField" => "test3", "author" => ["firstName" => "tester2"]],
["myField" => "test1", "author" => ["firstName" => "tester1"]],
],
],
'read with sorter files title DESC' => [
'fixture' => '_SortPlugin',
'query' => <<<GRAPHQL
query {
readDataObjectFakes(sort: { myField: ASC }) {
nodes {
myField
files(sort: { title: DESC }) {
title
}
}
}
}
GRAPHQL,
'expected' => [
["myField" => "test1", "files" => [["title" => "file4"], ["title" => "file3"], ["title" => "file2"], ["title" => "file1"]]],
["myField" => "test2", "files" => []],
["myField" => "test3", "files" => []],
],
],
'read with sorter files ParentID ACS, name DESC' => [
'fixture' => '_SortPlugin',
'query' => <<<GRAPHQL
query {
readDataObjectFakes(sort: { myField: ASC }) {
nodes {
myField
files(sort: { ParentID: ASC, name: DESC }) {
title
}
}
}
}
GRAPHQL,
'expected' => [
["myField" => "test1", "files" => [["title" => "file2"],["title" => "file1"], ["title" => "file4"],["title" => "file3"]]],
["myField" => "test2", "files" => []],
["myField" => "test3", "files" => []],
],
],
'read with sorter files ParentID DESC, name ASC' => [
'fixture' => '_SortPlugin',
'query' => <<<GRAPHQL
query {
readDataObjectFakes(sort: { myField: ASC }) {
nodes {
myField
files(sort: { ParentID: DESC, name: ASC }) {
title
}
}
}
}
GRAPHQL,
'expected' => [
["myField" => "test1", "files" => [["title" => "file3"],["title" => "file4"], ["title" => "file1"],["title" => "file2"]]],
["myField" => "test2", "files" => []],
["myField" => "test3", "files" => []],
],
],
'read with sorter files name ASC, ParentID DESC' => [
'fixture' => '_SortPlugin',
'query' => <<<GRAPHQL
query {
readDataObjectFakes(sort: { myField: ASC }) {
nodes {
myField
files(sort: { name: ASC, ParentID: DESC }) {
title
}
}
}
}
GRAPHQL,
'expected' => [
["myField" => "test1", "files" => [["title" => "file3"],["title" => "file1"], ["title" => "file4"],["title" => "file2"]]],
["myField" => "test2", "files" => []],
["myField" => "test3", "files" => []],
],
],
'read with sorter files name DESC, ParentID ASC' => [
'fixture' => '_SortPlugin',
'query' => <<<GRAPHQL
query {
readDataObjectFakes(sort: { myField: ASC }) {
nodes {
myField
files(sort: { name: DESC, ParentID: ASC }) {
title
}
}
}
}
GRAPHQL,
'expected' => [
["myField" => "test1", "files" => [["title" => "file2"],[ "title" => "file4"],["title" => "file1"],["title" => "file3"]]],
["myField" => "test2", "files" => []],
["myField" => "test3", "files" => []],
],
],
];
}

/**
* @dataProvider provideFilterAndSortOnlyRead
*/
public function testFilterAndSortOnlyRead($fixture, $query)
public function testFilterAndSortOnlyRead(string $fixture, string $query, array $expected)
{
$author = Member::create(['FirstName' => 'tester1']);
$author->write();
Expand All @@ -709,18 +814,34 @@ public function testFilterAndSortOnlyRead($fixture, $query)
$dataObject3 = DataObjectFake::create(['MyField' => 'test3', 'AuthorID' => $author2->ID]);
$dataObject3->write();

$file1 = File::create(['Title' => 'file1', 'Name' => 'asc_name']);
$file1->ParentID = 1;
$file1->write();

$file2 = File::create(['Title' => 'file2', 'Name' => 'desc_name']);
$file2->ParentID = 1;
$file2->write();

$file3 = File::create(['Title' => 'file3', 'Name' => 'asc_name']);
$file3->ParentID = 2;
$file3->write();

$file4 = File::create(['Title' => 'file4', 'Name' => 'desc_name']);
$file4->ParentID = 2;
$file4->write();

$dataObject1->Files()->add($file1);
$dataObject1->Files()->add($file2);
$dataObject1->Files()->add($file3);
$dataObject1->Files()->add($file4);

$factory = new TestSchemaBuilder(['_' . __FUNCTION__ . $fixture]);
$schema = $this->createSchema($factory);

$result = $this->querySchema($schema, $query);
$this->assertSuccess($result);
$records = $result['data']['readDataObjectFakes']['nodes'] ?? [];
$this->assertResults([
["myField" => "test2", "author" => ["firstName" => "tester2"]],
["myField" => "test3", "author" => ["firstName" => "tester2"]],
["myField" => "test1", "author" => ["firstName" => "tester1"]],
], $records);
$this->assertResults($expected, $records);
}

public function testAggregateProperties()
Expand Down
25 changes: 25 additions & 0 deletions tests/Schema/_testFilterAndSortOnlyRead_SortPlugin/models.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
SilverStripe\GraphQL\Tests\Fake\DataObjectFake:
operations:
read:
plugins:
sort:
before: paginateList
fields:
myField: true
AuthorID: true
author:
fields:
firstName: true
files:
fields:
id: true
name: true
title: true
ParentID: true
plugins:
sorter:
fields:
id: true
title: true
name: true
ParentID: true

0 comments on commit b2e9018

Please sign in to comment.