graphql-php/tests/Utils/ValueFromAstTest.php

255 lines
9.6 KiB
PHP
Raw Normal View History

2016-11-19 00:15:40 +03:00
<?php
2018-09-02 13:44:21 +03:00
declare(strict_types=1);
2016-11-19 00:15:40 +03:00
namespace GraphQL\Tests\Utils;
use GraphQL\Language\Parser;
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\InputObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Utils\AST;
2018-09-02 13:44:21 +03:00
use GraphQL\Utils\Utils;
2018-07-29 18:43:10 +03:00
use PHPUnit\Framework\TestCase;
2016-11-19 00:15:40 +03:00
2018-07-29 18:43:10 +03:00
class ValueFromAstTest extends TestCase
2016-11-19 00:15:40 +03:00
{
2018-09-02 13:44:21 +03:00
/** @var InputObjectType */
private $inputObj;
2016-11-19 00:15:40 +03:00
/**
* @see it('rejects empty input')
2016-11-19 00:15:40 +03:00
*/
public function testRejectsEmptyInput() : void
2016-11-19 00:15:40 +03:00
{
$this->assertEquals(Utils::undefined(), AST::valueFromAST(null, Type::boolean()));
}
/**
* @see it('converts according to input coercion rules')
2016-11-19 00:15:40 +03:00
*/
public function testConvertsAccordingToInputCoercionRules() : void
2016-11-19 00:15:40 +03:00
{
$this->runTestCase(Type::boolean(), 'true', true);
$this->runTestCase(Type::boolean(), 'false', false);
$this->runTestCase(Type::int(), '123', 123);
$this->runTestCase(Type::float(), '123', 123);
$this->runTestCase(Type::float(), '123.456', 123.456);
$this->runTestCase(Type::string(), '"abc123"', 'abc123');
$this->runTestCase(Type::id(), '123456', '123456');
$this->runTestCase(Type::id(), '"123456"', '123456');
}
2018-09-02 13:44:21 +03:00
private function runTestCase($type, $valueText, $expected)
{
$this->assertEquals($expected, AST::valueFromAST(Parser::parseValue($valueText), $type));
}
2016-11-19 00:15:40 +03:00
/**
* @see it('does not convert when input coercion rules reject a value')
2016-11-19 00:15:40 +03:00
*/
public function testDoesNotConvertWhenInputCoercionRulesRejectAValue() : void
2016-11-19 00:15:40 +03:00
{
$undefined = Utils::undefined();
$this->runTestCase(Type::boolean(), '123', $undefined);
$this->runTestCase(Type::int(), '123.456', $undefined);
$this->runTestCase(Type::int(), 'true', $undefined);
$this->runTestCase(Type::int(), '"123"', $undefined);
$this->runTestCase(Type::float(), '"123"', $undefined);
$this->runTestCase(Type::string(), '123', $undefined);
$this->runTestCase(Type::string(), 'true', $undefined);
$this->runTestCase(Type::id(), '123.456', $undefined);
}
/**
* @see it('converts enum values according to input coercion rules')
2016-11-19 00:15:40 +03:00
*/
public function testConvertsEnumValuesAccordingToInputCoercionRules() : void
2016-11-19 00:15:40 +03:00
{
$testEnum = new EnumType([
2018-09-02 13:44:21 +03:00
'name' => 'TestColor',
2016-11-19 00:15:40 +03:00
'values' => [
2018-09-02 13:44:21 +03:00
'RED' => ['value' => 1],
2016-11-19 00:15:40 +03:00
'GREEN' => ['value' => 2],
2018-09-02 13:44:21 +03:00
'BLUE' => ['value' => 3],
'NULL' => ['value' => null],
],
2016-11-19 00:15:40 +03:00
]);
$this->runTestCase($testEnum, 'RED', 1);
$this->runTestCase($testEnum, 'BLUE', 3);
$this->runTestCase($testEnum, '3', Utils::undefined());
$this->runTestCase($testEnum, '"BLUE"', Utils::undefined());
$this->runTestCase($testEnum, 'null', null);
2017-07-04 16:19:52 +03:00
$this->runTestCase($testEnum, 'NULL', null);
2016-11-19 00:15:40 +03:00
}
/**
* @see it('coerces to null unless non-null')
2016-11-19 00:15:40 +03:00
*/
public function testCoercesToNullUnlessNonNull() : void
2016-11-19 00:15:40 +03:00
{
$this->runTestCase(Type::boolean(), 'null', null);
$this->runTestCase(Type::nonNull(Type::boolean()), 'null', Utils::undefined());
}
/**
* @see it('coerces lists of values')
2016-11-19 00:15:40 +03:00
*/
public function testCoercesListsOfValues() : void
2016-11-19 00:15:40 +03:00
{
$listOfBool = Type::listOf(Type::boolean());
2018-09-02 13:44:21 +03:00
$undefined = Utils::undefined();
2016-11-19 00:15:40 +03:00
2018-09-02 13:44:21 +03:00
$this->runTestCase($listOfBool, 'true', [true]);
2016-11-19 00:15:40 +03:00
$this->runTestCase($listOfBool, '123', $undefined);
$this->runTestCase($listOfBool, 'null', null);
2018-09-02 13:44:21 +03:00
$this->runTestCase($listOfBool, '[true, false]', [true, false]);
2016-11-19 00:15:40 +03:00
$this->runTestCase($listOfBool, '[true, 123]', $undefined);
2018-09-02 13:44:21 +03:00
$this->runTestCase($listOfBool, '[true, null]', [true, null]);
2016-11-19 00:15:40 +03:00
$this->runTestCase($listOfBool, '{ true: true }', $undefined);
}
/**
* @see it('coerces non-null lists of values')
2016-11-19 00:15:40 +03:00
*/
public function testCoercesNonNullListsOfValues() : void
2016-11-19 00:15:40 +03:00
{
$nonNullListOfBool = Type::nonNull(Type::listOf(Type::boolean()));
2018-09-02 13:44:21 +03:00
$undefined = Utils::undefined();
2016-11-19 00:15:40 +03:00
2018-09-02 13:44:21 +03:00
$this->runTestCase($nonNullListOfBool, 'true', [true]);
2016-11-19 00:15:40 +03:00
$this->runTestCase($nonNullListOfBool, '123', $undefined);
$this->runTestCase($nonNullListOfBool, 'null', $undefined);
2018-09-02 13:44:21 +03:00
$this->runTestCase($nonNullListOfBool, '[true, false]', [true, false]);
2016-11-19 00:15:40 +03:00
$this->runTestCase($nonNullListOfBool, '[true, 123]', $undefined);
2018-09-02 13:44:21 +03:00
$this->runTestCase($nonNullListOfBool, '[true, null]', [true, null]);
2016-11-19 00:15:40 +03:00
}
/**
* @see it('coerces lists of non-null values')
2016-11-19 00:15:40 +03:00
*/
public function testCoercesListsOfNonNullValues() : void
2016-11-19 00:15:40 +03:00
{
$listOfNonNullBool = Type::listOf(Type::nonNull(Type::boolean()));
2018-09-02 13:44:21 +03:00
$undefined = Utils::undefined();
2016-11-19 00:15:40 +03:00
2018-09-02 13:44:21 +03:00
$this->runTestCase($listOfNonNullBool, 'true', [true]);
2016-11-19 00:15:40 +03:00
$this->runTestCase($listOfNonNullBool, '123', $undefined);
$this->runTestCase($listOfNonNullBool, 'null', null);
2018-09-02 13:44:21 +03:00
$this->runTestCase($listOfNonNullBool, '[true, false]', [true, false]);
2016-11-19 00:15:40 +03:00
$this->runTestCase($listOfNonNullBool, '[true, 123]', $undefined);
$this->runTestCase($listOfNonNullBool, '[true, null]', $undefined);
}
/**
* @see it('coerces non-null lists of non-null values')
2016-11-19 00:15:40 +03:00
*/
public function testCoercesNonNullListsOfNonNullValues() : void
2016-11-19 00:15:40 +03:00
{
$nonNullListOfNonNullBool = Type::nonNull(Type::listOf(Type::nonNull(Type::boolean())));
2018-09-02 13:44:21 +03:00
$undefined = Utils::undefined();
2016-11-19 00:15:40 +03:00
2018-09-02 13:44:21 +03:00
$this->runTestCase($nonNullListOfNonNullBool, 'true', [true]);
2016-11-19 00:15:40 +03:00
$this->runTestCase($nonNullListOfNonNullBool, '123', $undefined);
$this->runTestCase($nonNullListOfNonNullBool, 'null', $undefined);
2018-09-02 13:44:21 +03:00
$this->runTestCase($nonNullListOfNonNullBool, '[true, false]', [true, false]);
2016-11-19 00:15:40 +03:00
$this->runTestCase($nonNullListOfNonNullBool, '[true, 123]', $undefined);
$this->runTestCase($nonNullListOfNonNullBool, '[true, null]', $undefined);
}
/**
* @see it('coerces input objects according to input coercion rules')
2016-11-19 00:15:40 +03:00
*/
public function testCoercesInputObjectsAccordingToInputCoercionRules() : void
2016-11-19 00:15:40 +03:00
{
$testInputObj = $this->inputObj();
2018-09-02 13:44:21 +03:00
$undefined = Utils::undefined();
2016-11-19 00:15:40 +03:00
$this->runTestCase($testInputObj, 'null', null);
$this->runTestCase($testInputObj, '123', $undefined);
$this->runTestCase($testInputObj, '[]', $undefined);
$this->runTestCase($testInputObj, '{ int: 123, requiredBool: false }', ['int' => 123, 'requiredBool' => false]);
2018-09-02 13:44:21 +03:00
$this->runTestCase(
$testInputObj,
'{ bool: true, requiredBool: false }',
['int' => 42, 'bool' => true, 'requiredBool' => false]
);
2016-11-19 00:15:40 +03:00
$this->runTestCase($testInputObj, '{ int: true, requiredBool: true }', $undefined);
$this->runTestCase($testInputObj, '{ requiredBool: null }', $undefined);
$this->runTestCase($testInputObj, '{ bool: true }', $undefined);
}
2018-09-02 13:44:21 +03:00
private function inputObj()
{
return $this->inputObj ?: $this->inputObj = new InputObjectType([
'name' => 'TestInput',
'fields' => [
'int' => ['type' => Type::int(), 'defaultValue' => 42],
'bool' => ['type' => Type::boolean()],
'requiredBool' => ['type' => Type::nonNull(Type::boolean())],
],
]);
}
2016-11-19 00:15:40 +03:00
/**
* @see it('accepts variable values assuming already coerced')
2016-11-19 00:15:40 +03:00
*/
public function testAcceptsVariableValuesAssumingAlreadyCoerced() : void
2016-11-19 00:15:40 +03:00
{
$this->runTestCaseWithVars([], Type::boolean(), '$var', Utils::undefined());
2018-09-02 13:44:21 +03:00
$this->runTestCaseWithVars(['var' => true], Type::boolean(), '$var', true);
$this->runTestCaseWithVars(['var' => null], Type::boolean(), '$var', null);
}
private function runTestCaseWithVars($variables, $type, $valueText, $expected)
{
$this->assertEquals($expected, AST::valueFromAST(Parser::parseValue($valueText), $type, $variables));
2016-11-19 00:15:40 +03:00
}
/**
* @see it('asserts variables are provided as items in lists')
2016-11-19 00:15:40 +03:00
*/
public function testAssertsVariablesAreProvidedAsItemsInLists() : void
2016-11-19 00:15:40 +03:00
{
2018-09-02 13:44:21 +03:00
$listOfBool = Type::listOf(Type::boolean());
2016-11-19 00:15:40 +03:00
$listOfNonNullBool = Type::listOf(Type::nonNull(Type::boolean()));
2018-09-02 13:44:21 +03:00
$this->runTestCaseWithVars([], $listOfBool, '[ $foo ]', [null]);
2016-11-19 00:15:40 +03:00
$this->runTestCaseWithVars([], $listOfNonNullBool, '[ $foo ]', Utils::undefined());
2018-09-02 13:44:21 +03:00
$this->runTestCaseWithVars(['foo' => true], $listOfNonNullBool, '[ $foo ]', [true]);
2016-11-19 00:15:40 +03:00
// Note: variables are expected to have already been coerced, so we
// do not expect the singleton wrapping behavior for variables.
2018-09-02 13:44:21 +03:00
$this->runTestCaseWithVars(['foo' => true], $listOfNonNullBool, '$foo', true);
$this->runTestCaseWithVars(['foo' => [true]], $listOfNonNullBool, '$foo', [true]);
2016-11-19 00:15:40 +03:00
}
/**
* @see it('omits input object fields for unprovided variables')
2016-11-19 00:15:40 +03:00
*/
public function testOmitsInputObjectFieldsForUnprovidedVariables() : void
2016-11-19 00:15:40 +03:00
{
$testInputObj = $this->inputObj();
$this->runTestCaseWithVars(
[],
$testInputObj,
'{ int: $foo, bool: $foo, requiredBool: true }',
2018-09-02 13:44:21 +03:00
['int' => 42, 'requiredBool' => true]
2016-11-19 00:15:40 +03:00
);
$this->runTestCaseWithVars(
[],
$testInputObj,
'{ requiredBool: $foo }',
Utils::undefined()
);
$this->runTestCaseWithVars(
2018-09-02 13:44:21 +03:00
['foo' => true],
2016-11-19 00:15:40 +03:00
$testInputObj,
'{ requiredBool: $foo }',
2018-09-02 13:44:21 +03:00
['int' => 42, 'requiredBool' => true]
2016-11-19 00:15:40 +03:00
);
}
}