Skip to content

Commit 2f7f577

Browse files
committed
select-fields: fix always behaviour
This _probably_ got broken after #327 landed. There were no tests before, so it didn't got noticed.
1 parent 1d03e0b commit 2f7f577

File tree

6 files changed

+261
-1
lines changed

6 files changed

+261
-1
lines changed

src/Support/SelectFields.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,10 @@ protected static function addFieldToSelect($field, array &$select, ?string $pare
334334
}
335335

336336
if ($forRelation && ! array_key_exists($field, $select)) {
337-
$select[$field] = true;
337+
$select['fields'][$field] = [
338+
'args' => [],
339+
'fields' => true,
340+
];
338341
} elseif (! $forRelation && ! in_array($field, $select)) {
339342
$field = $parentTable ? ($parentTable.'.'.$field) : $field;
340343
if (! in_array($field, $select)) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rebing\GraphQL\Tests\Database\SelectFields\AlwaysTests;
6+
7+
use Closure;
8+
use GraphQL\Type\Definition\Type;
9+
use Rebing\GraphQL\Support\Query;
10+
use GraphQL\Type\Definition\ResolveInfo;
11+
use Rebing\GraphQL\Support\SelectFields;
12+
use Rebing\GraphQL\Support\Facades\GraphQL;
13+
use Rebing\GraphQL\Tests\Support\Models\Post;
14+
15+
class AlwaysQuery extends Query
16+
{
17+
protected $attributes = [
18+
'name' => 'alwaysQuery',
19+
];
20+
21+
public function type(): Type
22+
{
23+
return Type::listOf(GraphQL::type('Post'));
24+
}
25+
26+
public function resolve($root, $args, $contxt, ResolveInfo $info, Closure $getSelectFields)
27+
{
28+
/** @var SelectFields $selectFields */
29+
$selectFields = $getSelectFields();
30+
31+
return Post
32+
::select($selectFields->getSelect())
33+
->with($selectFields->getRelations())
34+
->get();
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rebing\GraphQL\Tests\Database\SelectFields\AlwaysTests;
6+
7+
use Rebing\GraphQL\Tests\TestCaseDatabase;
8+
use Rebing\GraphQL\Support\Facades\GraphQL;
9+
use Rebing\GraphQL\Tests\Support\Models\Post;
10+
use Rebing\GraphQL\Tests\Support\Models\Comment;
11+
use Rebing\GraphQL\Tests\Support\Traits\SqlAssertionTrait;
12+
13+
class AlwaysTest extends TestCaseDatabase
14+
{
15+
use SqlAssertionTrait;
16+
17+
public function testAlwaysSingleField(): void
18+
{
19+
/** @var Post $post */
20+
$post = factory(Post::class)
21+
->create([
22+
'body' => 'post body',
23+
'title' => 'post title',
24+
]);
25+
$comment = factory(Comment::class)
26+
->create([
27+
'body' => 'comment body',
28+
'post_id' => $post->id,
29+
'title' => 'comment title',
30+
]);
31+
32+
$query = <<<'GRAQPHQL'
33+
{
34+
alwaysQuery {
35+
body
36+
title
37+
comments {
38+
id
39+
}
40+
}
41+
}
42+
GRAQPHQL;
43+
44+
$this->sqlCounterReset();
45+
46+
$result = $this->graphql($query);
47+
48+
$this->assertSqlQueries(<<<'SQL'
49+
select "posts"."body", "posts"."title", "posts"."id" from "posts";
50+
select "comments"."id", "comments"."post_id", "comments"."body" from "comments" where "comments"."post_id" in (?) order by "comments"."id" asc;
51+
SQL
52+
);
53+
54+
$expectedResult = [
55+
'data' => [
56+
'alwaysQuery' => [
57+
[
58+
'body' => 'post body',
59+
'title' => 'post title',
60+
'comments' => [
61+
[
62+
'id' => (string) $comment->id,
63+
],
64+
],
65+
],
66+
],
67+
],
68+
];
69+
$this->assertEquals($expectedResult, $result);
70+
}
71+
72+
protected function getEnvironmentSetUp($app)
73+
{
74+
parent::getEnvironmentSetUp($app);
75+
76+
$app['config']->set('graphql.schemas.default', [
77+
'query' => [
78+
AlwaysQuery::class,
79+
],
80+
]);
81+
82+
$app['config']->set('graphql.schemas.custom', null);
83+
84+
$app['config']->set('graphql.types', [
85+
CommentType::class,
86+
PostType::class,
87+
]);
88+
}
89+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rebing\GraphQL\Tests\Database\SelectFields\AlwaysTests;
6+
7+
use GraphQL\Type\Definition\Type;
8+
use Rebing\GraphQL\Support\Type as GraphQLType;
9+
use Rebing\GraphQL\Tests\Support\Models\Comment;
10+
11+
class CommentType extends GraphQLType
12+
{
13+
protected $attributes = [
14+
'name' => 'Comment',
15+
'model' => Comment::class,
16+
];
17+
18+
public function fields(): array
19+
{
20+
return [
21+
'body' => [
22+
'type' => Type::string(),
23+
],
24+
'id' => [
25+
'type' => Type::nonNull(Type::ID()),
26+
],
27+
'title' => [
28+
'type' => Type::nonNull(Type::string()),
29+
],
30+
];
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rebing\GraphQL\Tests\Database\SelectFields\AlwaysTests;
6+
7+
use GraphQL\Type\Definition\Type;
8+
use Rebing\GraphQL\Support\Facades\GraphQL;
9+
use Rebing\GraphQL\Tests\Support\Models\Post;
10+
use Rebing\GraphQL\Support\Type as GraphQLType;
11+
12+
class PostType extends GraphQLType
13+
{
14+
protected $attributes = [
15+
'name' => 'Post',
16+
'model' => Post::class,
17+
];
18+
19+
public function fields(): array
20+
{
21+
return [
22+
'body' => [
23+
'type' => Type::string(),
24+
],
25+
'comments' => [
26+
'type' => Type::nonNull(Type::listOf(Type::nonNull(GraphQL::type('Comment')))),
27+
'always' => 'body',
28+
],
29+
'id' => [
30+
'type' => Type::nonNull(Type::ID()),
31+
],
32+
'title' => [
33+
'type' => Type::nonNull(Type::string()),
34+
],
35+
];
36+
}
37+
}

tests/TestCase.php

+63
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use GraphQL\Type\Definition\FieldDefinition;
1616
use Orchestra\Database\ConsoleServiceProvider;
1717
use Orchestra\Testbench\TestCase as BaseTestCase;
18+
use PHPUnit\Framework\ExpectationFailedException;
1819
use Symfony\Component\Console\Tester\CommandTester;
1920
use Rebing\GraphQL\Tests\Support\Objects\ExampleType;
2021
use Rebing\GraphQL\Tests\Support\Objects\ExamplesQuery;
@@ -170,4 +171,66 @@ protected function runCommand(Command $command, array $arguments = [], array $in
170171

171172
return $tester;
172173
}
174+
175+
/**
176+
* Helper to dispatch an internal GraphQL requests
177+
*
178+
* @param string $query
179+
* @param array $options
180+
* @return array Supports the following options:
181+
* - `expectErrors` (default: false): if no errors are expected but present, let's the test fail
182+
*/
183+
protected function graphql(string $query, array $options = []): array
184+
{
185+
$expectErrors = $options['expectErrors'] ?? false;
186+
187+
$result = GraphQL::query($query);
188+
189+
$assertMessage = null;
190+
191+
if (!$expectErrors && isset($result['errors'])) {
192+
193+
$appendErrors = '';
194+
if (isset($result['errors'][0]['trace'])) {
195+
$appendErrors = "\n\n" . $this->formatSafeTrace($result['errors'][0]['trace']);
196+
unset($result['errors'][0]['trace']);
197+
}
198+
199+
$assertMessage = "Probably unexpected error in GraphQL response:\n"
200+
. var_export($result, true)
201+
. $appendErrors;
202+
}
203+
204+
if ($assertMessage) {
205+
throw new ExpectationFailedException($assertMessage);
206+
}
207+
208+
return $result;
209+
}
210+
/**
211+
* Converts the trace as generated from \GraphQL\Error\FormattedError::toSafeTrace
212+
* to a more human-readable string for a failed test
213+
*
214+
* @param array $trace
215+
* @return string
216+
*/
217+
private function formatSafeTrace(array $trace): string
218+
{
219+
return implode("\n",
220+
array_map(function (array $row, int $index): string {
221+
$line = "#$index ";
222+
$line .= $row['file'] ?? '';
223+
if (isset($row['line'])) {
224+
$line .= "({$row['line']}) :";
225+
}
226+
if (isset($row['call'])) {
227+
$line .= ' ' . $row['call'];
228+
}
229+
if (isset($row['function'])) {
230+
$line .= ' ' . $row['function'];
231+
}
232+
233+
return $line;
234+
}, $trace, array_keys($trace)));
235+
}
173236
}

0 commit comments

Comments
 (0)