Tests for Config

This commit is contained in:
vladar 2016-12-07 23:21:23 +07:00
parent c5bba0e7d4
commit 51d816d280
4 changed files with 708 additions and 33 deletions

View File

@ -59,6 +59,14 @@ class Config
self::$allowCustomOptions = $allowCustomOptions;
}
/**
* @return bool
*/
public static function isValidationEnabled()
{
return self::$enableValidation;
}
/**
* @param array $config
* @param array $definition
@ -90,20 +98,6 @@ class Config
}
}
/**
* @param $definition
* @param int $flags
* @return \stdClass
*/
public static function map(array $definition, $flags = 0)
{
$tmp = new \stdClass();
$tmp->isMap = true;
$tmp->definition = $definition;
$tmp->flags = $flags;
return $tmp;
}
/**
* @param array|int $definition
* @param int $flags
@ -133,7 +127,7 @@ class Config
if (!empty($unexpectedKeys)) {
if (!self::$allowCustomOptions) {
trigger_error(sprintf('"%s" type definition: Non-standard keys "%s" ' . $suffix, $typeName, implode(', ', $unexpectedKeys)));
trigger_error(sprintf('Error in "%s" type definition: Non-standard keys "%s" ' . $suffix, $typeName, implode(', ', $unexpectedKeys)));
}
$map = array_intersect_key($map, $definitions);
}
@ -143,7 +137,7 @@ class Config
$missingKeys = array_keys(array_diff_key($requiredKeys, $map));
Utils::invariant(
empty($missingKeys),
"Error in '$typeName' type definition: Required keys missing: '%s' $suffix", implode(', ', $missingKeys)
'Error in "' . $typeName . '" type definition: Required keys missing: "%s" %s', implode(', ', $missingKeys), $suffix
);
// Make sure that every map value is valid given the definition
@ -163,30 +157,26 @@ class Config
private static function validateEntry($typeName, $key, $value, $def, $pathStr)
{
$type = Utils::getVariableType($value);
$err = 'Error in "'.$typeName.'" type definition: expecting %s at "' . $pathStr . '", but got "' . $type . '"';
$err = 'Error in "'.$typeName.'" type definition: expecting "%s" at "' . $pathStr . '", but got "' . $type . '"';
if ($def instanceof \stdClass) {
if ($def->flags & self::REQUIRED === 0 && $value === null) {
if (($def->flags & self::REQUIRED) === 0 && $value === null) {
return ;
}
if (($def->flags & self::MAYBE_THUNK) > 0) {
// TODO: consider wrapping thunk with other function to force validation of value returned by thunk
Utils::invariant(is_array($value) || is_callable($value), $err, 'array or callable');
} else {
Utils::invariant(is_array($value), $err, 'array');
}
if (!empty($def->isMap)) {
if ($def->flags & self::KEY_AS_NAME) {
$value += ['name' => $key];
}
self::validateMap($typeName, $value, $def->definition, $pathStr);
} else if (!empty($def->isArray)) {
if (!empty($def->isArray)) {
if ($def->flags & self::REQUIRED) {
Utils::invariant(!empty($value), 'Error in "'.$typeName.'" type definition: ' . "Value at '$pathStr' cannot be empty array");
}
$err = 'Error in "'.$typeName.'" type definition: ' . "Each entry at '$pathStr' must be an array, but '%s' is '%s'";
$err = 'Error in "'.$typeName.'" type definition: ' . "Each entry at '$pathStr' must be an array, but entry at '%s' is '%s'";
foreach ($value as $arrKey => $arrValue) {
if (is_array($def->definition)) {
@ -199,7 +189,7 @@ class Config
Utils::invariant(is_array($arrValue), $err, $arrKey, Utils::getVariableType($arrValue));
if ($def->flags & self::KEY_AS_NAME) {
if ($def->flags & self::KEY_AS_NAME && is_string($arrKey)) {
$arrValue += ['name' => $arrKey];
}
self::validateMap($typeName, $arrValue, $def->definition, "$pathStr:$arrKey");
@ -214,7 +204,7 @@ class Config
Utils::invariant(is_int($def), 'Error in "'.$typeName.'" type definition: ' . "Definition for '$pathStr' is expected to be single integer value");
if ($def & self::REQUIRED) {
Utils::invariant($value !== null, 'Value at "%s" can not be null', $pathStr);
Utils::invariant($value !== null, 'Error in "'.$typeName.'" type definition: ' . 'Value at "%s" can not be null', $pathStr);
}
if (null === $value) {
@ -234,7 +224,7 @@ class Config
Utils::invariant(is_numeric($value), $err, 'numeric');
break;
case $def & self::FLOAT:
Utils::invariant(is_float($value), $err, 'float');
Utils::invariant(is_float($value) || is_int($value), $err, 'float');
break;
case $def & self::INT:
Utils::invariant(is_int($value), $err, 'int');
@ -246,6 +236,7 @@ class Config
Utils::invariant(is_scalar($value), $err, 'scalar');
break;
case $def & self::NAME:
Utils::invariant(is_string($value), $err, 'name');
Utils::invariant(
preg_match('~^[_a-zA-Z][_a-zA-Z0-9]*$~', $value),
'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "%s" does not.',
@ -256,28 +247,28 @@ class Config
Utils::invariant(
is_callable($value) || $value instanceof InputType,
$err,
'callable or InputType definition'
'InputType definition'
);
break;
case $def & self::OUTPUT_TYPE:
Utils::invariant(
is_callable($value) || $value instanceof OutputType,
$err,
'callable or OutputType definition'
'OutputType definition'
);
break;
case $def & self::INTERFACE_TYPE:
Utils::invariant(
is_callable($value) || $value instanceof InterfaceType,
$err,
'callable or InterfaceType definition'
'InterfaceType definition'
);
break;
case $def & self::OBJECT_TYPE:
Utils::invariant(
is_callable($value) || $value instanceof ObjectType,
$err,
'callable or ObjectType definition'
'ObjectType definition'
);
break;
default:

676
tests/Type/ConfigTest.php Normal file
View File

@ -0,0 +1,676 @@
<?php
namespace Type;
use GraphQL\Error\InvariantViolation;
use GraphQL\Type\Definition\Config;
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\InputObjectType;
use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
class ConfigTest extends \PHPUnit_Framework_TestCase
{
public static function tearDownAfterClass()
{
Config::disableValidation();
}
public function testToggling()
{
// Disabled by default
$this->assertEquals(false, Config::isValidationEnabled());
Config::validate(['test' => []], ['test' => Config::STRING]); // must not throw
Config::enableValidation();
$this->assertEquals(true, Config::isValidationEnabled());
try {
Config::validate(['test' => []], ['test' => Config::STRING]);
$this->fail('Expected exception not thrown');
} catch (\Exception $e) {
}
Config::disableValidation();
$this->assertEquals(false, Config::isValidationEnabled());
Config::validate(['test' => []], ['test' => Config::STRING]);
}
public function testValidateString()
{
$this->expectValidationPasses(
[
'test' => 'string',
'empty' => ''
],
[
'test' => Config::STRING,
'empty' => Config::STRING
]
);
$this->expectValidationThrows(
['test' => 1],
['test' => Config::STRING],
$this->typeError('expecting "string" at "test", but got "integer"')
);
}
public function testArray()
{
$this->expectValidationPasses(
['test' => [
[],
['nested' => 'A'],
['nested' => null]
]],
['test' => Config::arrayOf(
['nested' => Config::STRING]
)]
);
$this->expectValidationThrows(
['test' => [
null
]],
['test' => Config::arrayOf(
['nested' => Config::STRING]
)],
$this->typeError("Each entry at 'test' must be an array, but entry at '0' is 'NULL'")
);
$this->expectValidationPasses(
['test' => null],
['test' => Config::arrayOf(
['nested' => Config::STRING]
)]
);
$this->expectValidationThrows(
['test' => null],
['test' => Config::arrayOf(
['nested' => Config::STRING],
Config::REQUIRED
)],
$this->typeError('expecting "array" at "test", but got "NULL"')
);
// Check validation nesting:
$this->expectValidationPasses(
['nest' => [
['nest' => [
['test' => 'value']
]]
]],
['nest' => Config::arrayOf([
'nest' => Config::arrayOf([
'test' => Config::STRING
])
])]
);
$this->expectValidationThrows(
['nest' => [
['nest' => [
['test' => 'notInt']
]]
]],
['nest' => Config::arrayOf([
'nest' => Config::arrayOf([
'test' => Config::INT
])
])],
$this->typeError('expecting "int" at "nest:0:nest:0:test", but got "string"')
);
// Check arrays of types:
$this->expectValidationPasses(
['nest' => [
Type::string(),
Type::int()
]],
['nest' => Config::arrayOf(
Config::OUTPUT_TYPE, Config::REQUIRED
)]
);
// Check arrays of types:
$this->expectValidationThrows(
['nest' => [
Type::string(),
new InputObjectType(['name' => 'test', 'fields' => []])
]],
['nest' => Config::arrayOf(
Config::OUTPUT_TYPE, Config::REQUIRED
)],
$this->typeError('expecting "OutputType definition" at "nest:1", but got "test"')
);
}
public function testRequired()
{
$this->expectValidationPasses(
['required' => ''],
['required' => Config::STRING | Config::REQUIRED]
);
$this->expectValidationThrows(
[],
['required' => Config::STRING | Config::REQUIRED],
$this->typeError('Required keys missing: "required" ')
);
$this->expectValidationThrows(
['required' => null],
['required' => Config::STRING | Config::REQUIRED],
$this->typeError('Value at "required" can not be null')
);
$this->expectValidationPasses(
['test' => [
['nested' => '']
]],
['test' => Config::arrayOf([
'nested' => Config::STRING | Config::REQUIRED
])]
);
$this->expectValidationThrows(
['test' => [
[]
]],
['test' => Config::arrayOf([
'nested' => Config::STRING | Config::REQUIRED
])],
$this->typeError('Required keys missing: "nested" at test:0')
);
$this->expectValidationThrows(
['test' => [
['nested' => null]
]],
['test' => Config::arrayOf([
'nested' => Config::STRING | Config::REQUIRED
])],
$this->typeError('Value at "test:0:nested" can not be null')
);
$this->expectValidationPasses(
['test' => [
['nested' => null]
]],
['test' => Config::arrayOf(
['nested' => Config::STRING],
Config::REQUIRED
)]
);
$this->expectValidationThrows(
['test' => [
]],
['test' => Config::arrayOf(
['nested' => Config::STRING],
Config::REQUIRED
)],
$this->typeError("Value at 'test' cannot be empty array")
);
}
public function testKeyAsName()
{
$this->expectValidationPasses(
['test' => [
'name1' => ['key1' => null],
['name' => 'name1'],
]],
['test' => Config::arrayOf(
['name' => Config::STRING | Config::REQUIRED, 'key1' => Config::STRING],
Config::KEY_AS_NAME
)]
);
$this->expectValidationThrows(
['test' => [
'name1' => ['key1' => null]
]],
['test' => Config::arrayOf(
['name' => Config::STRING | Config::REQUIRED, 'key1' => Config::STRING]
)],
$this->typeError('Required keys missing: "name" at test:name1')
);
$this->expectValidationThrows(
['test' => [
['key1' => null]
]],
['test' => Config::arrayOf(
['name' => Config::STRING | Config::REQUIRED, 'key1' => Config::STRING],
Config::KEY_AS_NAME
)],
$this->typeError('Required keys missing: "name" at test:0')
);
}
public function testMaybeThunk()
{
$this->expectValidationPasses(
[
'test' => [
['nested' => ''],
['nested' => '1'],
],
'testThunk' => function() {
// Currently config won't validate thunk return value
}
],
[
'test' => Config::arrayOf(
['nested' => Config::STRING | Config::REQUIRED],
Config::MAYBE_THUNK
),
'testThunk' => Config::arrayOf(
['nested' => Config::STRING | Config::REQUIRED],
Config::MAYBE_THUNK
)
]
);
$this->expectValidationThrows(
[
'testThunk' => function() {
}
],
[
'testThunk' => Config::arrayOf(
['nested' => Config::STRING | Config::REQUIRED]
)
],
$this->typeError('expecting "array" at "testThunk", but got "Closure"')
);
$this->expectValidationThrows(
[
'testThunk' => 1
],
[
'testThunk' => Config::arrayOf(
['nested' => Config::STRING | Config::REQUIRED],
Config::MAYBE_THUNK
)
],
$this->typeError('expecting "array or callable" at "testThunk", but got "integer"')
);
}
public function testMaybeType()
{
$type = new ObjectType([
'name' => 'Test',
'fields' => []
]);
$this->expectValidationPasses(
['test' => [
$type,
['type' => $type],
]],
['test' => Config::arrayOf(
['type' => Config::OBJECT_TYPE | Config::REQUIRED],
Config::MAYBE_TYPE
)]
);
$this->expectValidationThrows(
['test' => [
['type' => 'str']
]],
['test' => Config::arrayOf(
['type' => Config::OBJECT_TYPE | Config::REQUIRED],
Config::MAYBE_TYPE
)],
$this->typeError('expecting "ObjectType definition" at "test:0:type", but got "string"')
);
$this->expectValidationThrows(
['test' => [
$type
]],
['test' => Config::arrayOf(
['name' => Config::OBJECT_TYPE | Config::REQUIRED]
)],
$this->typeError("Each entry at 'test' must be an array, but entry at '0' is 'Test'")
);
}
public function testMaybeName()
{
$this->expectValidationPasses(
['test' => [
'some-name',
['name' => 'other-name'],
]],
['test' => Config::arrayOf(
['name' => Config::STRING | Config::REQUIRED],
Config::MAYBE_NAME
)]
);
$this->expectValidationThrows(
['test' => [
'some-name'
]],
['test' => Config::arrayOf(
['name' => Config::OBJECT_TYPE | Config::REQUIRED]
)],
$this->typeError("Each entry at 'test' must be an array, but entry at '0' is 'string'")
);
$this->expectValidationPasses(
['test' => [
'some-key' => 'some-name',
'some-name'
]],
['test' => Config::arrayOf(
['name' => Config::STRING | Config::REQUIRED],
Config::MAYBE_NAME | Config::KEY_AS_NAME
)]
);
}
public function getValidValues()
{
return [
// $type, $validValue
[Config::ANY, null],
[Config::ANY, 0],
[Config::ANY, ''],
[Config::ANY, '0'],
[Config::ANY, 1],
[Config::ANY, function() {}],
[Config::ANY, []],
[Config::ANY, new \stdClass()],
[Config::STRING, null],
[Config::STRING, ''],
[Config::STRING, '0'],
[Config::STRING, 'anything'],
[Config::BOOLEAN, null],
[Config::BOOLEAN, false],
[Config::BOOLEAN, true],
[Config::INT, null],
[Config::INT, 0],
[Config::INT, 1],
[Config::INT, -1],
[Config::INT, 5000000],
[Config::INT, -5000000],
[Config::FLOAT, null],
[Config::FLOAT, 0],
[Config::FLOAT, 0.0],
[Config::FLOAT, 0.1],
[Config::FLOAT, -12.5],
[Config::NUMERIC, null],
[Config::NUMERIC, '0'],
[Config::NUMERIC, 0],
[Config::NUMERIC, 1],
[Config::NUMERIC, 0.0],
[Config::NUMERIC, 1.0],
[Config::NUMERIC, -1.0],
[Config::NUMERIC, -1],
[Config::NUMERIC, 1],
[Config::CALLBACK, null],
[Config::CALLBACK, function() {}],
[Config::CALLBACK, [$this, 'getValidValues']],
[Config::SCALAR, null],
[Config::SCALAR, 0],
[Config::SCALAR, 1],
[Config::SCALAR, 0.0],
[Config::SCALAR, 1.0],
[Config::SCALAR, true],
[Config::SCALAR, false],
[Config::SCALAR, ''],
[Config::SCALAR, '0'],
[Config::SCALAR, 'anything'],
[Config::NAME, null],
[Config::NAME, 'CamelCaseIsOk'],
[Config::NAME, 'underscore_is_ok'],
[Config::NAME, 'numbersAreOk0123456789'],
[Config::INPUT_TYPE, null],
[Config::INPUT_TYPE, new InputObjectType(['name' => 'test', 'fields' => []])],
[Config::INPUT_TYPE, new EnumType(['name' => 'test2', 'values' => ['A', 'B', 'C']])],
[Config::INPUT_TYPE, Type::string()],
[Config::INPUT_TYPE, Type::int()],
[Config::INPUT_TYPE, Type::float()],
[Config::INPUT_TYPE, Type::boolean()],
[Config::INPUT_TYPE, Type::id()],
[Config::INPUT_TYPE, Type::listOf(Type::string())],
[Config::INPUT_TYPE, Type::nonNull(Type::string())],
[Config::OUTPUT_TYPE, null],
[Config::OUTPUT_TYPE, new ObjectType(['name' => 'test3', 'fields' => []])],
[Config::OUTPUT_TYPE, new EnumType(['name' => 'test4', 'values' => ['A', 'B', 'C']])],
[Config::OUTPUT_TYPE, Type::string()],
[Config::OUTPUT_TYPE, Type::int()],
[Config::OUTPUT_TYPE, Type::float()],
[Config::OUTPUT_TYPE, Type::boolean()],
[Config::OUTPUT_TYPE, Type::id()],
[Config::OBJECT_TYPE, null],
[Config::OBJECT_TYPE, new ObjectType(['name' => 'test6', 'fields' => []])],
[Config::INTERFACE_TYPE, null],
[Config::INTERFACE_TYPE, new InterfaceType(['name' => 'test7', 'fields' => []])],
];
}
/**
* @dataProvider getValidValues
*/
public function testValidValues($type, $validValue)
{
$this->expectValidationPasses(
['test' => $validValue],
['test' => $type]
);
}
public function getInvalidValues()
{
return [
// $type, $typeLabel, $invalidValue, $actualTypeLabel
[Config::STRING, 'string', 1, 'integer'],
[Config::STRING, 'string', 0, 'integer'],
[Config::STRING, 'string', false, 'boolean'],
[Config::STRING, 'string', function() {}, 'Closure'],
[Config::STRING, 'string', [], 'array'],
[Config::STRING, 'string', new \stdClass(), 'stdClass'],
[Config::BOOLEAN, 'boolean', '', 'string'],
[Config::BOOLEAN, 'boolean', 1, 'integer'],
[Config::BOOLEAN, 'boolean', function() {}, 'Closure'],
[Config::BOOLEAN, 'boolean', [], 'array'],
[Config::BOOLEAN, 'boolean', new \stdClass(), 'stdClass'],
[Config::INT, 'int', false, 'boolean'],
[Config::INT, 'int', '', 'string'],
[Config::INT, 'int', '0', 'string'],
[Config::INT, 'int', '1', 'string'],
[Config::INT, 'int', function() {}, 'Closure'],
[Config::INT, 'int', [], 'array'],
[Config::INT, 'int', new \stdClass(), 'stdClass'],
[Config::FLOAT, 'float', '', 'string'],
[Config::FLOAT, 'float', '0', 'string'],
[Config::FLOAT, 'float', function() {}, 'Closure'],
[Config::FLOAT, 'float', [], 'array'],
[Config::FLOAT, 'float', new \stdClass(), 'stdClass'],
[Config::NUMERIC, 'numeric', '', 'string'],
[Config::NUMERIC, 'numeric', 'tmp', 'string'],
[Config::NUMERIC, 'numeric', [], 'array'],
[Config::NUMERIC, 'numeric', new \stdClass(), 'stdClass'],
[Config::NUMERIC, 'numeric', function() {}, 'Closure'],
[Config::CALLBACK, 'callable', 1, 'integer'],
[Config::CALLBACK, 'callable', '', 'string'],
[Config::CALLBACK, 'callable', [], 'array'],
[Config::CALLBACK, 'callable', new \stdClass(), 'stdClass'],
[Config::SCALAR, 'scalar', [], 'array'],
[Config::SCALAR, 'scalar', new \stdClass(), 'stdClass'],
[Config::SCALAR, 'scalar', function() {}, 'Closure'],
[Config::NAME, 'name', 5, 'integer'],
[Config::NAME, 'name', function() {}, 'Closure'],
[Config::NAME, 'name', [], 'array'],
[Config::NAME, 'name', new \stdClass(), 'stdClass'],
[Config::NAME, 'name', '', null, 'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "" does not.'],
[Config::NAME, 'name', '0', null, 'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "0" does not.'],
[Config::NAME, 'name', '4abc', null, 'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "4abc" does not.'],
[Config::NAME, 'name', 'specialCharsAreBad!', null, 'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "specialCharsAreBad!" does not.'],
[Config::INPUT_TYPE, 'InputType definition', new ObjectType(['name' => 'test3', 'fields' => []]), 'test3'],
[Config::INPUT_TYPE, 'InputType definition', '', 'string'],
[Config::INPUT_TYPE, 'InputType definition', 'test', 'string'],
[Config::INPUT_TYPE, 'InputType definition', 1, 'integer'],
[Config::INPUT_TYPE, 'InputType definition', 0.5, 'double'],
[Config::INPUT_TYPE, 'InputType definition', false, 'boolean'],
[Config::INPUT_TYPE, 'InputType definition', [], 'array'],
[Config::INPUT_TYPE, 'InputType definition', new \stdClass(), 'stdClass'],
[Config::OUTPUT_TYPE, 'OutputType definition', new InputObjectType(['name' => 'InputTypeTest']), 'InputTypeTest'],
[Config::OBJECT_TYPE, 'ObjectType definition', '', 'string'],
[Config::OBJECT_TYPE, 'ObjectType definition', new InputObjectType(['name' => 'InputTypeTest2']), 'InputTypeTest2'],
[Config::INTERFACE_TYPE, 'InterfaceType definition', new ObjectType(['name' => 'ObjectTypeTest']), 'ObjectTypeTest'],
[Config::INTERFACE_TYPE, 'InterfaceType definition', 'InputTypeTest2', 'string'],
];
}
/**
* @dataProvider getInvalidValues
*/
public function testInvalidValues($type, $typeLabel, $invalidValue, $actualTypeLabel = null, $expectedFullError = null)
{
if (!$expectedFullError) {
$expectedFullError = $this->typeError(
$invalidValue === null ?
'Value at "test" can not be null' :
'expecting "' . $typeLabel . '" at "test", but got "' . $actualTypeLabel . '"'
);
}
$this->expectValidationThrows(
['test' => $invalidValue],
['test' => $type],
$expectedFullError
);
}
public function testErrorMessageContainsTypeName()
{
$this->expectValidationThrows(
[
'name' => 'TypeName',
'test' => 'notInt'
],
[
'name' => Config::STRING | Config::REQUIRED,
'test' => Config::INT
],
$this->typeError('expecting "int" at "test", but got "string"', 'TypeName')
);
}
public function testValidateField()
{
Config::enableValidation();
// Should just validate:
Config::validateField(
'TypeName',
['test' => 'value'],
['test' => Config::STRING]
);
// Should include type name in error
try {
Config::validateField(
'TypeName',
['test' => 'notInt'],
['test' => Config::INT]
);
$this->fail('Expected exception not thrown');
} catch (InvariantViolation $e) {
$this->assertEquals(
$this->typeError('expecting "int" at "(Unknown Field):test", but got "string"', 'TypeName'),
$e->getMessage()
);
}
// Should include field type in error when field name is unknown:
try {
Config::validateField(
'TypeName',
['type' => Type::string()],
['name' => Config::STRING | Config::REQUIRED, 'type' => Config::OUTPUT_TYPE]
);
$this->fail('Expected exception not thrown');
} catch (InvariantViolation $e) {
$this->assertEquals(
$this->typeError('Required keys missing: "name" at (Unknown Field of type: String)', 'TypeName'),
$e->getMessage()
);
}
// Should include field name in error when field name is set:
try {
Config::validateField(
'TypeName',
['name' => 'fieldName', 'test' => 'notInt'],
['name' => Config::STRING, 'test' => Config::INT]
);
$this->fail('Expected exception not thrown');
} catch (InvariantViolation $e) {
$this->assertEquals(
$this->typeError('expecting "int" at "test", but got "string"', 'TypeName'),
$e->getMessage()
);
}
}
public function testAllowCustomOptions()
{
// Disabled by default when validation is enabled
Config::enableValidation(true);
Config::validate(
['test' => 'value', 'test2' => 'value'],
['test' => Config::STRING]
);
Config::enableValidation(false);
try {
Config::validate(
['test' => 'value', 'test2' => 'value'],
['test' => Config::STRING]
);
$this->fail('Expected exception not thrown');
} catch (\PHPUnit_Framework_Error_Notice $e) {
$this->assertEquals(
$this->typeError('Non-standard keys "test2" '),
$e->getMessage()
);
}
}
private function expectValidationPasses($config, $definition)
{
Config::enableValidation(false);
Config::validate($config, $definition);
}
private function expectValidationThrows($config, $definition, $expectedError)
{
Config::enableValidation(false);
try {
Config::validate($config, $definition);
$this->fail('Expected exception not thrown: ' . $expectedError);
} catch (InvariantViolation $e) {
$this->assertEquals($expectedError, $e->getMessage());
}
}
private function typeError($err, $typeName = null)
{
return 'Error in "'. ($typeName ?: '(Unnamed Type)') . '" type definition: ' . $err;
}
}

View File

@ -469,7 +469,7 @@ class DefinitionTest extends \PHPUnit_Framework_TestCase
$this->fail('Expected exception not thrown');
} catch (\Exception $e) {
$this->assertSame(
'Error in "BadUnion" type definition: expecting callable or ObjectType definition at "types:0", but got "' . Utils::getVariableType($type) . '"',
'Error in "BadUnion" type definition: expecting "ObjectType definition" at "types:0", but got "' . Utils::getVariableType($type) . '"',
$e->getMessage()
);
}

View File

@ -2,6 +2,7 @@
namespace GraphQL\Tests\Type;
use GraphQL\Schema;
use GraphQL\Type\Definition\Config;
use GraphQL\Type\Definition\CustomScalarType;
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\InputObjectType;
@ -392,6 +393,9 @@ class SchemaValidatorTest extends \PHPUnit_Framework_TestCase
public function testRejectsASchemaThatUsesAnInputTypeAsAField()
{
$enabled = Config::isValidationEnabled();
Config::disableValidation();
$kinds = [
'GraphQL\Type\Definition\ObjectType',
];
@ -415,6 +419,10 @@ class SchemaValidatorTest extends \PHPUnit_Framework_TestCase
$validationResult[0]->message
);
}
if ($enabled) {
Config::enableValidation();
}
}
public function testAcceptsASchemaThatSimplyHasAnInputTypeAsAFieldArg()