Skip to content

Commit 4777050

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 4777050

File tree

6 files changed

+260
-1
lines changed

6 files changed

+260
-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,88 @@
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\Tests\Support\Models\Post;
9+
use Rebing\GraphQL\Tests\Support\Models\Comment;
10+
use Rebing\GraphQL\Tests\Support\Traits\SqlAssertionTrait;
11+
12+
class AlwaysTest extends TestCaseDatabase
13+
{
14+
use SqlAssertionTrait;
15+
16+
public function testAlwaysSingleField(): void
17+
{
18+
/** @var Post $post */
19+
$post = factory(Post::class)
20+
->create([
21+
'body' => 'post body',
22+
'title' => 'post title',
23+
]);
24+
$comment = factory(Comment::class)
25+
->create([
26+
'body' => 'comment body',
27+
'post_id' => $post->id,
28+
'title' => 'comment title',
29+
]);
30+
31+
$query = <<<'GRAQPHQL'
32+
{
33+
alwaysQuery {
34+
body
35+
title
36+
comments {
37+
id
38+
}
39+
}
40+
}
41+
GRAQPHQL;
42+
43+
$this->sqlCounterReset();
44+
45+
$result = $this->graphql($query);
46+
47+
$this->assertSqlQueries(<<<'SQL'
48+
select "posts"."body", "posts"."title", "posts"."id" from "posts";
49+
select "comments"."id", "comments"."post_id", "comments"."body" from "comments" where "comments"."post_id" in (?) order by "comments"."id" asc;
50+
SQL
51+
);
52+
53+
$expectedResult = [
54+
'data' => [
55+
'alwaysQuery' => [
56+
[
57+
'body' => 'post body',
58+
'title' => 'post title',
59+
'comments' => [
60+
[
61+
'id' => (string) $comment->id,
62+
],
63+
],
64+
],
65+
],
66+
],
67+
];
68+
$this->assertEquals($expectedResult, $result);
69+
}
70+
71+
protected function getEnvironmentSetUp($app)
72+
{
73+
parent::getEnvironmentSetUp($app);
74+
75+
$app['config']->set('graphql.schemas.default', [
76+
'query' => [
77+
AlwaysQuery::class,
78+
],
79+
]);
80+
81+
$app['config']->set('graphql.schemas.custom', null);
82+
83+
$app['config']->set('graphql.types', [
84+
CommentType::class,
85+
PostType::class,
86+
]);
87+
}
88+
}
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+
$appendErrors = '';
193+
if (isset($result['errors'][0]['trace'])) {
194+
$appendErrors = "\n\n".$this->formatSafeTrace($result['errors'][0]['trace']);
195+
unset($result['errors'][0]['trace']);
196+
}
197+
198+
$assertMessage = "Probably unexpected error in GraphQL response:\n"
199+
.var_export($result, true)
200+
.$appendErrors;
201+
}
202+
203+
if ($assertMessage) {
204+
throw new ExpectationFailedException($assertMessage);
205+
}
206+
207+
return $result;
208+
}
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)