Skip to content

Commit 3a827ea

Browse files
committed
Chronos and Date can parse literals too
So we can use literals in GraphQL queries instead of separated variables
1 parent 796b7a6 commit 3a827ea

File tree

4 files changed

+100
-25
lines changed

4 files changed

+100
-25
lines changed

src/Api/Scalar/ChronosType.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,15 @@ public function parseValue($value): ?Chronos
5959

6060
/**
6161
* Parses an externally provided literal value to use as an input (e.g. in Query AST).
62-
*
63-
* @return null|string
6462
*/
65-
public function parseLiteral(Node $ast, ?array $variables = null)
63+
public function parseLiteral(Node $ast, ?array $variables = null): ?Chronos
6664
{
6765
// Note: throwing GraphQL\Error\Error vs \UnexpectedValueException to benefit from GraphQL
6866
// error location in query:
6967
if (!($ast instanceof StringValueNode)) {
7068
throw new Error('Query error: Can only parse strings got: ' . $ast->kind, $ast);
7169
}
7270

73-
return $ast->value;
71+
return $this->parseValue($ast->value);
7472
}
7573
}

src/Api/Scalar/DateType.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ public function parseValue($value): Date
5454
/**
5555
* Parses an externally provided literal value to use as an input (e.g. in Query AST).
5656
*/
57-
public function parseLiteral(Node $ast, ?array $variables = null): ?string
57+
public function parseLiteral(Node $ast, ?array $variables = null): Date
5858
{
5959
// Note: throwing GraphQL\Error\Error vs \UnexpectedValueException to benefit from GraphQL
6060
// error location in query:
6161
if (!($ast instanceof StringValueNode)) {
6262
throw new Error('Query error: Can only parse strings got: ' . $ast->kind, $ast);
6363
}
6464

65-
return $ast->value;
65+
return $this->parseValue($ast->value);
6666
}
6767
}

tests/Api/Scalar/ChronosTypeTest.php

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
namespace EcodevTests\Felix\Api\Scalar;
66

7+
use Cake\Chronos\Chronos;
78
use Ecodev\Felix\Api\Scalar\ChronosType;
9+
use GraphQL\Language\AST\IntValueNode;
10+
use GraphQL\Language\AST\StringValueNode;
811
use PHPUnit\Framework\TestCase;
912

1013
final class ChronosTypeTest extends TestCase
@@ -25,8 +28,16 @@ protected function tearDown(): void
2528
date_default_timezone_set($this->timezone);
2629
}
2730

31+
public function testSerialize(): void
32+
{
33+
$type = new ChronosType();
34+
$date = new Chronos('2018-09-15T00:00:00+02:00');
35+
$actual = $type->serialize($date);
36+
self::assertSame('2018-09-15T00:00:00+02:00', $actual);
37+
}
38+
2839
/**
29-
* @dataProvider providerParseValue
40+
* @dataProvider providerValue
3041
*/
3142
public function testParseValue(string $input, ?string $expected): void
3243
{
@@ -39,7 +50,32 @@ public function testParseValue(string $input, ?string $expected): void
3950
self::assertSame($expected, $actual);
4051
}
4152

42-
public function providerParseValue(): array
53+
/**
54+
* @dataProvider providerValue
55+
*/
56+
public function testParseLiteral(string $input, ?string $expected): void
57+
{
58+
$type = new ChronosType();
59+
$ast = new StringValueNode(['value' => $input]);
60+
61+
$actual = $type->parseLiteral($ast);
62+
if ($actual) {
63+
$actual = $actual->format('c');
64+
}
65+
66+
self::assertSame($expected, $actual);
67+
}
68+
69+
public function testParseLiteralAsInt(): void
70+
{
71+
$type = new ChronosType();
72+
$ast = new IntValueNode(['value' => 123]);
73+
74+
$this->expectExceptionMessage('Query error: Can only parse strings got: IntValue');
75+
$type->parseLiteral($ast);
76+
}
77+
78+
public function providerValue(): array
4379
{
4480
return [
4581
'UTC' => ['2018-09-14T22:00:00.000Z', '2018-09-15T00:00:00+02:00'],

tests/Api/Scalar/DateTypeTest.php

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,76 @@
66

77
use Cake\Chronos\Date;
88
use Ecodev\Felix\Api\Scalar\DateType;
9+
use GraphQL\Language\AST\IntValueNode;
10+
use GraphQL\Language\AST\StringValueNode;
911
use PHPUnit\Framework\TestCase;
1012

1113
final class DateTypeTest extends TestCase
1214
{
13-
public function testTimezoneIsIgnored(): void
15+
/**
16+
* @var string
17+
*/
18+
private $timezone;
19+
20+
protected function setUp(): void
1421
{
15-
$date = new Date();
16-
$offsetFromGmt = $date->dst ? $date->offsetHours - 1 : $date->offsetHours;
17-
$timezone = sprintf('+%02u:00', $offsetFromGmt);
22+
$this->timezone = date_default_timezone_get();
23+
date_default_timezone_set('Europe/Zurich');
24+
}
1825

26+
protected function tearDown(): void
27+
{
28+
date_default_timezone_set($this->timezone);
29+
}
30+
31+
public function testSerialize(): void
32+
{
1933
$type = new DateType();
20-
$actual = $type->parseValue('2010-02-09');
21-
self::assertInstanceOf(Date::class, $actual);
22-
self::assertSame('2010-02-09T00:00:00' . $timezone, $actual->format('c'));
34+
$date = new Date('2010-02-03');
35+
$actual = $type->serialize($date);
36+
self::assertSame('2010-02-03', $actual);
37+
}
2338

24-
$actual = $type->parseValue('2010-02-09T23:00:00');
39+
/**
40+
* @dataProvider providerValues
41+
*/
42+
public function testParseValue(string $input, string $expected): void
43+
{
44+
$type = new DateType();
45+
$actual = $type->parseValue($input);
2546
self::assertInstanceOf(Date::class, $actual);
26-
self::assertSame('2010-02-09T00:00:00' . $timezone, $actual->format('c'));
47+
self::assertSame($expected, $actual->format('c'));
48+
}
2749

28-
$actual = $type->parseValue('2010-02-09T02:00:00+08:00');
50+
/**
51+
* @dataProvider providerValues
52+
*/
53+
public function testParseLiteral(string $input, string $expected): void
54+
{
55+
$type = new DateType();
56+
$ast = new StringValueNode(['value' => $input]);
57+
58+
$actual = $type->parseLiteral($ast);
2959
self::assertInstanceOf(Date::class, $actual);
30-
self::assertSame('2010-02-09T00:00:00' . $timezone, $actual->format('c'), 'timezone should be ignored');
60+
self::assertSame($expected, $actual->format('c'));
61+
}
3162

32-
$date = new Date('2010-02-03');
33-
$actual = $type->serialize($date);
34-
self::assertSame('2010-02-03', $actual);
63+
public function testParseLiteralAsInt(): void
64+
{
65+
$type = new DateType();
66+
$ast = new IntValueNode(['value' => 123]);
3567

36-
$actual = $type->parseValue('2020-03-24T23:30:00+04.5:0-30');
37-
self::assertInstanceOf(Date::class, $actual);
38-
self::assertSame('2020-03-24T00:00:00' . $timezone, $actual->format('c'), 'timezone should be ignored');
68+
$this->expectExceptionMessage('Query error: Can only parse strings got: IntValue');
69+
$type->parseLiteral($ast);
70+
}
71+
72+
public function providerValues(): array
73+
{
74+
return [
75+
'normal' => ['2010-06-09', '2010-06-09T00:00:00+02:00'],
76+
'time should be ignored' => ['2010-06-09T23:00:00', '2010-06-09T00:00:00+02:00'],
77+
'timezone should be ignored' => ['2010-06-09T02:00:00+08:00', '2010-06-09T00:00:00+02:00'],
78+
'unusual timezone should be ignored' => ['2020-06-24T23:30:00+04.5:0-30', '2020-06-24T00:00:00+02:00'],
79+
];
3980
}
4081
}

0 commit comments

Comments
 (0)