Skip to content

Commit 4b78ca3

Browse files
committed
Add tests for StringScalar, use printSafeJson for consistent error messages
1 parent dd375cc commit 4b78ca3

File tree

8 files changed

+320
-75
lines changed

8 files changed

+320
-75
lines changed

src/Regex.php

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,6 @@
1313

1414
abstract class Regex extends ScalarType
1515
{
16-
/**
17-
* Return the Regex that the values are validated against.
18-
*
19-
* @return string
20-
*/
21-
abstract protected function regex(): string;
22-
2316
/**
2417
* This factory method allows you to create a Regex scalar in a one-liner.
2518
*
@@ -31,7 +24,8 @@ abstract protected function regex(): string;
3124
*/
3225
public static function make(string $name, string $description = null, string $regex): self
3326
{
34-
$regexClass = new class() extends Regex {
27+
$regexClass = new class() extends Regex
28+
{
3529
/**
3630
* Return the Regex that the values are validated against.
3731
*
@@ -44,14 +38,21 @@ protected function regex(): string
4438
return $this->regex;
4539
}
4640
};
47-
41+
4842
$regexClass->name = $name;
4943
$regexClass->description = $description;
5044
$regexClass->regex = $regex;
51-
45+
5246
return $regexClass;
5347
}
54-
48+
49+
/**
50+
* Return the Regex that the values are validated against.
51+
*
52+
* @return string
53+
*/
54+
abstract protected function regex(): string;
55+
5556
/**
5657
* Serializes an internal value to include in a response.
5758
*
@@ -62,14 +63,29 @@ protected function regex(): string
6263
public function serialize($value): string
6364
{
6465
$stringValue = assertString($value, InvariantViolation::class);
65-
66+
6667
if (!$this->matchesRegex($stringValue)) {
67-
throw new InvariantViolation("The given string $stringValue did not match the regex {$this->regex()}");
68+
throw new InvariantViolation(
69+
$this->unmatchedRegexMessage($stringValue)
70+
);
6871
}
69-
72+
7073
return $stringValue;
7174
}
72-
75+
76+
/**
77+
* @param string $value
78+
*
79+
* @return bool
80+
*/
81+
protected function matchesRegex(string $value): bool
82+
{
83+
return RegexValidator::match(
84+
$this->regex(),
85+
$value
86+
)->hasMatch();
87+
}
88+
7389
/**
7490
* Parses an externally provided value (query variable) to use as an input.
7591
*
@@ -82,24 +98,19 @@ public function serialize($value): string
8298
public function parseValue($value): string
8399
{
84100
$stringValue = assertString($value, Error::class);
85-
101+
86102
if (!$this->matchesRegex($stringValue)) {
87-
$safeValue = Utils::printSafeJson($stringValue);
88-
89-
throw new Error("The given value {$safeValue} did not match the regex {$this->regex()}");
103+
throw new Error(
104+
$this->unmatchedRegexMessage($stringValue)
105+
);
90106
}
91-
107+
92108
return $value;
93109
}
94-
110+
95111
/**
96112
* Parses an externally provided literal value (hardcoded in GraphQL query) to use as an input.
97113
*
98-
* E.g.
99-
* {
100-
* user(email: "[email protected]")
101-
* }
102-
*
103114
* @param Node $valueNode
104115
* @param array $variables
105116
*
@@ -110,26 +121,26 @@ public function parseValue($value): string
110121
public function parseLiteral($valueNode, array $variables = null): string
111122
{
112123
$value = assertStringLiteral($valueNode);
113-
124+
114125
if (!$this->matchesRegex($value)) {
115-
$safeValue = Utils::printSafeJson($value);
116-
117-
throw new Error("The given value {$safeValue} did not match the regex {$this->regex()}", [$valueNode]);
126+
throw new Error(
127+
$this->unmatchedRegexMessage($value),
128+
[$valueNode]
129+
);
118130
}
119-
131+
120132
return $value;
121133
}
122-
134+
123135
/**
124136
* @param string $value
125137
*
126-
* @return bool
138+
* @return string
127139
*/
128-
protected function matchesRegex(string $value): bool
140+
public function unmatchedRegexMessage(string $value): string
129141
{
130-
return RegexValidator::match(
131-
$this->regex(),
132-
$value
133-
)->hasMatch();
142+
$safeValue = Utils::printSafeJson($value);
143+
144+
return "The given value {$safeValue} did not match the regex {$this->regex()}";
134145
}
135146
}

src/StringScalar.php

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,6 @@
1212

1313
abstract class StringScalar extends ScalarType
1414
{
15-
/**
16-
* Check if the given string is a valid email.
17-
*
18-
* @param string $stringValue
19-
*
20-
* @return bool
21-
*/
22-
abstract protected function isValid(string $stringValue): bool;
23-
2415
/**
2516
* @param string $name The name that the scalar type will have in the schema.
2617
* @param string|null $description A description for the type.
@@ -30,7 +21,8 @@ abstract protected function isValid(string $stringValue): bool;
3021
*/
3122
public static function make(string $name, string $description = null, callable $isValid): self
3223
{
33-
$instance = new class() extends StringScalar {
24+
$instance = new class() extends StringScalar
25+
{
3426
/**
3527
* Check if the given string is a valid email.
3628
*
@@ -43,14 +35,23 @@ protected function isValid(string $stringValue): bool
4335
return call_user_func($this->isValid, $stringValue);
4436
}
4537
};
46-
38+
4739
$instance->name = $name;
4840
$instance->description = $description;
4941
$instance->isValid = $isValid;
50-
42+
5143
return $instance;
5244
}
53-
45+
46+
/**
47+
* Check if the given string is a valid email.
48+
*
49+
* @param string $stringValue
50+
*
51+
* @return bool
52+
*/
53+
abstract protected function isValid(string $stringValue): bool;
54+
5455
/**
5556
* Serializes an internal value to include in a response.
5657
*
@@ -61,14 +62,28 @@ protected function isValid(string $stringValue): bool
6162
public function serialize($value): string
6263
{
6364
$stringValue = assertString($value, InvariantViolation::class);
64-
65+
6566
if (!$this->isValid($stringValue)) {
66-
throw new InvariantViolation("The given string $stringValue is not a valid {$this->tryInferName()}.");
67+
throw new InvariantViolation(
68+
$this->invalidStringMessage($stringValue)
69+
);
6770
}
68-
71+
6972
return $stringValue;
7073
}
71-
74+
75+
/**
76+
* @param string $stringValue
77+
*
78+
* @return string
79+
*/
80+
public function invalidStringMessage(string $stringValue): string
81+
{
82+
$safeValue = Utils::printSafeJson($stringValue);
83+
84+
return "The given string {$safeValue} is not a valid {$this->tryInferName()}.";
85+
}
86+
7287
/**
7388
* Parses an externally provided value (query variable) to use as an input.
7489
*
@@ -81,16 +96,16 @@ public function serialize($value): string
8196
public function parseValue($value): string
8297
{
8398
$stringValue = assertString($value, Error::class);
84-
99+
85100
if (!$this->isValid($stringValue)) {
86-
$safeValue = Utils::printSafeJson($stringValue);
87-
88-
throw new Error("The given string {$safeValue} is not a valid {$this->tryInferName()}.");
101+
throw new Error(
102+
$this->invalidStringMessage($stringValue)
103+
);
89104
}
90-
105+
91106
return $stringValue;
92107
}
93-
108+
94109
/**
95110
* Parses an externally provided literal value (hardcoded in GraphQL query) to use as an input.
96111
*
@@ -109,13 +124,14 @@ public function parseValue($value): string
109124
public function parseLiteral($valueNode, array $variables = null): string
110125
{
111126
$stringValue = assertStringLiteral($valueNode);
112-
127+
113128
if (!$this->isValid($stringValue)) {
114-
$safeValue = Utils::printSafeJson($stringValue);
115-
116-
throw new Error("The given string {$safeValue} is not a valid {$this->tryInferName()}.", $valueNode);
129+
throw new Error(
130+
$this->invalidStringMessage($stringValue),
131+
$valueNode
132+
);
117133
}
118-
134+
119135
return $stringValue;
120136
}
121137
}

src/utils.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ function assertStringLiteral($valueNode): string
4949
function assertString($value, string $exceptionClass): string
5050
{
5151
if (!canBeString($value)) {
52-
$safeValue = Utils::printSafe($value);
52+
$safeValue = Utils::printSafeJson($value);
5353

5454
throw new $exceptionClass("The given value {$safeValue} can not be serialized.");
5555
}

tests/EmailTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public function testSerializeThrowsIfUnserializableValueIsGiven()
2525
public function testSerializeThrowsIfEmailIsInvalid()
2626
{
2727
$this->expectException(InvariantViolation::class);
28-
$this->expectExceptionMessage('The given string foo is not a valid Email.');
28+
$this->expectExceptionMessage('The given string "foo" is not a valid Email.');
2929

3030
(new Email())->serialize('foo');
3131
}

tests/Foo.php renamed to tests/MyRegex.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use MLL\GraphQLScalars\Regex;
88

9-
class Foo extends Regex
9+
class MyRegex extends Regex
1010
{
1111
public $description = 'Bar';
1212

tests/MyStringScalar.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests;
6+
7+
use MLL\GraphQLScalars\StringScalar;
8+
9+
class MyStringScalar extends StringScalar
10+
{
11+
public $description = 'Bar';
12+
13+
/**
14+
* Check if the given string is a valid email.
15+
*
16+
* @param string $stringValue
17+
*
18+
* @return bool
19+
*/
20+
protected function isValid(string $stringValue): bool
21+
{
22+
return $stringValue === 'foo';
23+
}
24+
}

tests/RegexTest.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public function regexClassProvider()
1818
return [
1919
[
2020
new class() extends Regex {
21-
public $name = 'Foo';
21+
public $name = 'MyRegex';
2222

2323
public $description = 'Bar';
2424

@@ -36,7 +36,7 @@ protected function regex(): string
3636
},
3737
],
3838
[
39-
new class(['name' => 'Foo', 'description' => 'Bar']) extends Regex {
39+
new class(['name' => 'MyRegex', 'description' => 'Bar']) extends Regex {
4040
/**
4141
* Return the Regex that the values are validated against.
4242
*
@@ -51,10 +51,10 @@ protected function regex(): string
5151
},
5252
],
5353
[
54-
new Foo(),
54+
new MyRegex(),
5555
],
5656
[
57-
Regex::make('Foo', 'Bar', '/foo/'),
57+
Regex::make('MyRegex', 'Bar', '/foo/'),
5858
],
5959
];
6060
}
@@ -64,7 +64,7 @@ protected function regex(): string
6464
*/
6565
public function testCreateNamedRegexClass(Regex $regex)
6666
{
67-
$this->assertSame('Foo', $regex->name);
67+
$this->assertSame('MyRegex', $regex->name);
6868
$this->assertSame('Bar', $regex->description);
6969
}
7070

@@ -87,7 +87,7 @@ public function testSerializeThrowsIfUnserializableValueIsGiven(Regex $regex)
8787
public function testSerializeThrowsIfRegexIsNotMatched(Regex $regex)
8888
{
8989
$this->expectException(InvariantViolation::class);
90-
$this->expectExceptionMessageRegExp('/did not match the regex/');
90+
$this->expectExceptionMessage($regex->unmatchedRegexMessage('bar'));
9191

9292
$regex->serialize('bar');
9393
}

0 commit comments

Comments
 (0)