Almost done with fields...
This commit is contained in:
parent
9e942d8221
commit
3be644b96f
13 changed files with 541 additions and 54 deletions
|
@ -8,6 +8,7 @@
|
|||
<excludeFolder url="file://$MODULE_DIR$/example/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/test/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
|
|
|
@ -7,6 +7,12 @@ class AliasContext extends Node {
|
|||
|
||||
AliasContext(this.NAME1, this.COLON, this.NAME2);
|
||||
|
||||
/// The actual name of the value.
|
||||
String get name => NAME1.text;
|
||||
|
||||
/// The aliased name of the value.
|
||||
String get alias => NAME2.text;
|
||||
|
||||
@override
|
||||
SourceSpan get span =>
|
||||
new SourceSpan(NAME1.span?.start, NAME2.span?.end, toSource());
|
||||
|
|
|
@ -15,21 +15,18 @@ class FieldContext extends Node {
|
|||
|
||||
@override
|
||||
SourceSpan get span {
|
||||
SourceLocation end = fieldName.end;
|
||||
|
||||
if (selectionSet != null)
|
||||
end = selectionSet.end;
|
||||
return fieldName.span.union(selectionSet.span);
|
||||
else if (directives.isNotEmpty)
|
||||
end = directives.last.end;
|
||||
else if (arguments.isNotEmpty) end = arguments.last.end;
|
||||
|
||||
return new SourceSpan(fieldName.start, end, toSource());
|
||||
return directives.fold<SourceSpan>(
|
||||
fieldName.span, (out, d) => out.union(d.span));
|
||||
if (arguments.isNotEmpty)
|
||||
return arguments.fold<SourceSpan>(
|
||||
fieldName.span, (out, a) => out.union(a.span));
|
||||
else
|
||||
return fieldName.span;
|
||||
}
|
||||
|
||||
@override
|
||||
String toSource() =>
|
||||
fieldName.toSource() +
|
||||
arguments.map((a) => a.toSource()).join() +
|
||||
directives.map((d) => d.toSource()).join() +
|
||||
(selectionSet?.toSource() ?? '');
|
||||
String toSource() => span.text;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ class FieldNameContext extends Node {
|
|||
assert(NAME != null || alias != null);
|
||||
}
|
||||
|
||||
String get name => NAME?.text;
|
||||
|
||||
@override
|
||||
SourceSpan get span => alias?.span ?? NAME.span;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ class TypeContext extends Node {
|
|||
final TypeNameContext typeName;
|
||||
final ListTypeContext listType;
|
||||
|
||||
bool get nonNullType => EXCLAMATION != null;
|
||||
bool get isNullable => EXCLAMATION == null;
|
||||
|
||||
TypeContext(this.typeName, this.listType, [this.EXCLAMATION]) {
|
||||
assert(typeName != null || listType != null);
|
||||
|
@ -42,7 +42,7 @@ class TypeContext extends Node {
|
|||
buf.write(listType.toSource());
|
||||
}
|
||||
|
||||
if (nonNullType) buf.write('!');
|
||||
if (!isNullable) buf.write('!');
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import '../token.dart';
|
|||
class TypeNameContext extends Node {
|
||||
final Token NAME;
|
||||
|
||||
String get name => NAME.text;
|
||||
|
||||
@override
|
||||
SourceSpan get span => NAME.span;
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ class VariableContext extends Node {
|
|||
String get name => NAME.text;
|
||||
|
||||
@override
|
||||
SourceSpan get span =>
|
||||
new SourceSpan(DOLLAR?.span?.start, NAME?.span?.end, toSource());
|
||||
SourceSpan get span => DOLLAR.span.union(NAME.span);
|
||||
// new SourceSpan(DOLLAR?.span?.start, NAME?.span?.end, toSource());
|
||||
|
||||
@override
|
||||
String toSource() => '\$${NAME.text}';
|
||||
|
|
|
@ -32,6 +32,8 @@ class Parser {
|
|||
return null;
|
||||
}
|
||||
|
||||
Token maybe(TokenType type) => next(type) ? current : null;
|
||||
|
||||
DocumentContext parseDocument() {}
|
||||
|
||||
FragmentDefinitionContext parseFragmentDefinition() {}
|
||||
|
@ -44,17 +46,98 @@ class Parser {
|
|||
|
||||
SelectionContext parseSelection() {}
|
||||
|
||||
FieldContext parseField() {}
|
||||
FieldContext parseField() {
|
||||
var fieldName = parseFieldName();
|
||||
if (fieldName != null) {
|
||||
var args = parseArguments();
|
||||
var directives = parseDirectives();
|
||||
var selectionSet = parseSelectionSet();
|
||||
return new FieldContext(fieldName, selectionSet)
|
||||
..arguments.addAll(args)
|
||||
..directives.addAll(directives);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
||||
FieldNameContext parseFieldName() {}
|
||||
|
||||
AliasContext parseAlias() {}
|
||||
FieldNameContext parseFieldName() {
|
||||
if (next(TokenType.NAME)) {
|
||||
var NAME1 = current;
|
||||
if (next(TokenType.COLON)) {
|
||||
var COLON = current;
|
||||
if (next(TokenType.NAME))
|
||||
return new FieldNameContext(
|
||||
null, new AliasContext(NAME1, COLON, current));
|
||||
else
|
||||
throw new SyntaxError.fromSourceLocation(
|
||||
'Expected name after colon in alias.', COLON.span.end);
|
||||
} else
|
||||
return new FieldNameContext(NAME1);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
||||
VariableDefinitionsContext parseVariableDefinitions() {}
|
||||
|
||||
VariableDefinitionContext parseVariableDefinition() {}
|
||||
VariableDefinitionContext parseVariableDefinition() {
|
||||
var variable = parseVariable();
|
||||
if (variable != null) {
|
||||
if (next(TokenType.COLON)) {
|
||||
var COLON = current;
|
||||
var type = parseType();
|
||||
if (type != null) {
|
||||
var defaultValue = parseDefaultValue();
|
||||
return new VariableDefinitionContext(
|
||||
variable, COLON, type, defaultValue);
|
||||
} else
|
||||
throw new SyntaxError.fromSourceLocation(
|
||||
'Expected type in variable definition.', COLON.span.end);
|
||||
} else
|
||||
throw new SyntaxError.fromSourceLocation(
|
||||
'Expected ":" in variable definition.', variable.span.end);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
||||
List<DirectiveContext> parseDirectives() {}
|
||||
TypeContext parseType() {
|
||||
var name = parseTypeName();
|
||||
if (name != null) {
|
||||
return new TypeContext(name, null, maybe(TokenType.EXCLAMATION));
|
||||
} else {
|
||||
var listType = parseListType();
|
||||
if (listType != null) {
|
||||
return new TypeContext(null, listType, maybe(TokenType.EXCLAMATION));
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
ListTypeContext parseListType() {
|
||||
if (next(TokenType.LBRACKET)) {
|
||||
var LBRACKET = current;
|
||||
var type = parseType();
|
||||
if (type != null) {
|
||||
if (next(TokenType.RBRACKET)) {
|
||||
return new ListTypeContext(LBRACKET, type, current);
|
||||
} else
|
||||
throw new SyntaxError.fromSourceLocation(
|
||||
'Expected "]" in list type.', type.span.end);
|
||||
} else
|
||||
throw new SyntaxError.fromSourceLocation(
|
||||
'Expected type after "[".', LBRACKET.span.end);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
||||
List<DirectiveContext> parseDirectives() {
|
||||
List<DirectiveContext> out = [];
|
||||
DirectiveContext d = parseDirective();
|
||||
while (d != null) {
|
||||
out.add(d);
|
||||
d = parseDirective();
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
DirectiveContext parseDirective() {
|
||||
if (next(TokenType.ARROBA)) {
|
||||
|
@ -95,6 +178,30 @@ class Parser {
|
|||
return null;
|
||||
}
|
||||
|
||||
List<ArgumentContext> parseArguments() {
|
||||
if (next(TokenType.LPAREN)) {
|
||||
var LPAREN = current;
|
||||
List<ArgumentContext> out = [];
|
||||
ArgumentContext arg = parseArgument();
|
||||
|
||||
while (arg != null) {
|
||||
out.add(arg);
|
||||
if (next(TokenType.COMMA))
|
||||
arg = parseArgument();
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (next(TokenType.RPAREN))
|
||||
return out;
|
||||
else
|
||||
throw new SyntaxError.fromSourceLocation(
|
||||
'Expected ")" in argument list.',
|
||||
out.isEmpty ? LPAREN.span.end : out.last.span.end);
|
||||
} else
|
||||
return [];
|
||||
}
|
||||
|
||||
ArgumentContext parseArgument() {
|
||||
if (next(TokenType.NAME)) {
|
||||
var NAME = current;
|
||||
|
@ -139,9 +246,33 @@ class Parser {
|
|||
return null;
|
||||
}
|
||||
|
||||
DefaultValueContext parseDefaultValue() {}
|
||||
DefaultValueContext parseDefaultValue() {
|
||||
if (next(TokenType.EQUALS)) {
|
||||
var EQUALS = current;
|
||||
var value = parseValue();
|
||||
if (value != null) {
|
||||
return new DefaultValueContext(EQUALS, value);
|
||||
} else
|
||||
throw new SyntaxError.fromSourceLocation(
|
||||
'Expected value after "=" sign.', EQUALS.span.end);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
||||
TypeConditionContext parseTypeCondition() {}
|
||||
TypeConditionContext parseTypeCondition() {
|
||||
var name = parseTypeName();
|
||||
if (name != null)
|
||||
return new TypeConditionContext(name);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
TypeNameContext parseTypeName() {
|
||||
if (next(TokenType.NAME)) {
|
||||
return new TypeNameContext(current);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
||||
ValueContext parseValue() {
|
||||
return parseStringValue() ??
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
import 'package:test/test.dart';
|
||||
import 'argument_test.dart' as argument;
|
||||
import 'directive_test.dart' as directive;
|
||||
import 'field_test.dart' as field;
|
||||
import 'type_test.dart' as type;
|
||||
import 'value_test.dart' as value;
|
||||
import 'variable_definition_test.dart' as variable_definition;
|
||||
import 'variable_test.dart' as variable;
|
||||
|
||||
main() {
|
||||
group('argument', argument.main);
|
||||
group('directive', directive.main);
|
||||
group('field', field.main);
|
||||
group('type', type.main);
|
||||
group('value', value.main);
|
||||
group('variable', variable.main);
|
||||
group('variable definition', variable_definition.main);
|
||||
}
|
||||
|
|
173
test/field_test.dart
Normal file
173
test/field_test.dart
Normal file
|
@ -0,0 +1,173 @@
|
|||
import 'package:graphql_parser/graphql_parser.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'common.dart';
|
||||
import 'argument_test.dart';
|
||||
import 'directive_test.dart';
|
||||
import 'value_test.dart';
|
||||
|
||||
main() {
|
||||
group('field name', () {
|
||||
test('plain field name', () {
|
||||
expect('foo', isFieldName('foo'));
|
||||
});
|
||||
test('alias', () {
|
||||
expect('foo: bar', isFieldName('foo', alias: 'bar'));
|
||||
});
|
||||
test('exceptions', () {
|
||||
expect(() => parseFieldName('foo:'), throwsSyntaxError);
|
||||
});
|
||||
});
|
||||
|
||||
test('arguments', () {
|
||||
expect('()', isArgumentList([]));
|
||||
expect(r'(a: 2)', isArgumentList([isArgument('a', 2)]));
|
||||
expect(r'(a: 2, b: $c)',
|
||||
isArgumentList([isArgument('a', 2), isArgument('b', 'c')]));
|
||||
});
|
||||
|
||||
group('field tests', () {
|
||||
test('plain field name', () {
|
||||
expect('foo', isField(fieldName: isFieldName('foo')));
|
||||
});
|
||||
|
||||
test('aliased field name', () {
|
||||
expect('foo: bar', isField(fieldName: isFieldName('foo', alias: 'bar')));
|
||||
});
|
||||
|
||||
test('with arguments', () {
|
||||
expect(
|
||||
r'foo (a: 2, b: $c)',
|
||||
isField(
|
||||
fieldName: isFieldName('foo'),
|
||||
arguments:
|
||||
isArgumentList([isArgument('a', 2), isArgument('b', 'c')])));
|
||||
});
|
||||
|
||||
test('with directives', () {
|
||||
expect(
|
||||
'foo: bar @bar @baz: 2 @quux (one: 1)',
|
||||
isField(
|
||||
fieldName: isFieldName('foo', alias: 'bar'),
|
||||
directives: isDirectiveList([
|
||||
isDirective('bar'),
|
||||
isDirective('baz', valueOrVariable: isValue(2)),
|
||||
isDirective('quux', argument: isArgument('one', 1))
|
||||
])));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
FieldContext parseField(String text) => parse(text).parseField();
|
||||
|
||||
FieldNameContext parseFieldName(String text) => parse(text).parseFieldName();
|
||||
|
||||
Matcher isArgumentList(List<Matcher> arguments) =>
|
||||
new _IsArgumentList(arguments);
|
||||
|
||||
Matcher isDirectiveList(List<Matcher> directives) =>
|
||||
new _IsDirectiveList(directives);
|
||||
|
||||
Matcher isField(
|
||||
{Matcher fieldName,
|
||||
Matcher arguments,
|
||||
Matcher directives,
|
||||
Matcher selectionSet}) =>
|
||||
new _IsField(fieldName, arguments, directives, selectionSet);
|
||||
|
||||
Matcher isFieldName(String name, {String alias}) =>
|
||||
new _IsFieldName(name, alias);
|
||||
|
||||
class _IsField extends Matcher {
|
||||
final Matcher fieldName, arguments, directives, selectionSet;
|
||||
|
||||
_IsField(this.fieldName, this.arguments, this.directives, this.selectionSet);
|
||||
|
||||
@override
|
||||
Description describe(Description description) {
|
||||
// Too lazy to make a real description...
|
||||
return description.add('is field');
|
||||
}
|
||||
|
||||
@override
|
||||
bool matches(item, Map matchState) {
|
||||
var field = item is FieldContext ? item : parseField(item);
|
||||
if (field == null) return false;
|
||||
if (fieldName != null && !fieldName.matches(field.fieldName, matchState))
|
||||
return false;
|
||||
if (arguments != null && !arguments.matches(field.arguments, matchState))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class _IsFieldName extends Matcher {
|
||||
final String name, alias;
|
||||
|
||||
_IsFieldName(this.name, this.alias);
|
||||
|
||||
@override
|
||||
Description describe(Description description) {
|
||||
if (alias != null)
|
||||
return description.add('is field with name "$name" and alias "$alias"');
|
||||
return description.add('is field with name "$name"');
|
||||
}
|
||||
|
||||
@override
|
||||
bool matches(item, Map matchState) {
|
||||
var fieldName = item is FieldNameContext ? item : parseFieldName(item);
|
||||
if (alias != null)
|
||||
return fieldName.alias?.name == name && fieldName.alias?.alias == alias;
|
||||
else
|
||||
return fieldName.name == name;
|
||||
}
|
||||
}
|
||||
|
||||
class _IsArgumentList extends Matcher {
|
||||
final List<Matcher> arguments;
|
||||
|
||||
_IsArgumentList(this.arguments);
|
||||
|
||||
@override
|
||||
Description describe(Description description) {
|
||||
return description.add('is list of ${arguments.length} argument(s)');
|
||||
}
|
||||
|
||||
@override
|
||||
bool matches(item, Map matchState) {
|
||||
var args =
|
||||
item is List<ArgumentContext> ? item : parse(item).parseArguments();
|
||||
|
||||
if (args.length != arguments.length) return false;
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (!arguments[i].matches(args[i], matchState)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class _IsDirectiveList extends Matcher {
|
||||
final List<Matcher> directives;
|
||||
|
||||
_IsDirectiveList(this.directives);
|
||||
|
||||
@override
|
||||
Description describe(Description description) {
|
||||
return description.add('is list of ${directives.length} directive(s)');
|
||||
}
|
||||
|
||||
@override
|
||||
bool matches(item, Map matchState) {
|
||||
var args =
|
||||
item is List<DirectiveContext> ? item : parse(item).parseDirectives();
|
||||
|
||||
if (args.length != directives.length) return false;
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (!directives[i].matches(args[i], matchState)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
95
test/type_test.dart
Normal file
95
test/type_test.dart
Normal file
|
@ -0,0 +1,95 @@
|
|||
import 'package:graphql_parser/graphql_parser.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'common.dart';
|
||||
|
||||
main() {
|
||||
test('nullable', () {
|
||||
expect('foo', isType('foo', isNullable: true));
|
||||
});
|
||||
|
||||
test('non-nullable', () {
|
||||
expect('foo!', isType('foo', isNullable: false));
|
||||
});
|
||||
|
||||
group('list type', () {
|
||||
group('nullable list type', () {
|
||||
test('with nullable', () {
|
||||
expect('[foo]', isListType(isType('foo', isNullable: true)));
|
||||
});
|
||||
|
||||
test('with non-nullable', () {
|
||||
expect('[foo!]', isListType(isType('foo', isNullable: false)));
|
||||
});
|
||||
});
|
||||
|
||||
group('non-nullable list type', () {
|
||||
test('with nullable', () {
|
||||
expect('[foo]!',
|
||||
isListType(isType('foo', isNullable: true), isNullable: false));
|
||||
});
|
||||
|
||||
test('with non-nullable', () {
|
||||
expect('[foo!]!',
|
||||
isListType(isType('foo', isNullable: false), isNullable: false));
|
||||
});
|
||||
});
|
||||
|
||||
test('exceptions', () {
|
||||
expect(() => parseType('[foo'), throwsSyntaxError);
|
||||
expect(() => parseType('['), throwsSyntaxError);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
TypeContext parseType(String text) => parse(text).parseType();
|
||||
|
||||
Matcher isListType(Matcher innerType, {bool isNullable}) =>
|
||||
new _IsListType(innerType, isNullable: isNullable != false);
|
||||
|
||||
Matcher isType(String name, {bool isNullable}) =>
|
||||
new _IsType(name, nonNull: isNullable != true);
|
||||
|
||||
class _IsListType extends Matcher {
|
||||
final Matcher innerType;
|
||||
final bool isNullable;
|
||||
|
||||
_IsListType(this.innerType, {this.isNullable});
|
||||
|
||||
@override
|
||||
Description describe(Description description) {
|
||||
var tok = isNullable != false ? 'nullable' : 'non-nullable';
|
||||
var desc = description.add('is $tok list type with an inner type that ');
|
||||
return innerType.describe(desc);
|
||||
}
|
||||
|
||||
@override
|
||||
bool matches(item, Map matchState) {
|
||||
var type = item is TypeContext ? item : parseType(item);
|
||||
if (type.listType == null) return false;
|
||||
if (type.isNullable != (isNullable != false)) return false;
|
||||
return innerType.matches(type.listType.type, matchState);
|
||||
}
|
||||
}
|
||||
|
||||
class _IsType extends Matcher {
|
||||
final String name;
|
||||
final bool nonNull;
|
||||
|
||||
_IsType(this.name, {this.nonNull});
|
||||
|
||||
@override
|
||||
Description describe(Description description) {
|
||||
if (nonNull == true)
|
||||
return description.add('is non-null type named "$name"');
|
||||
else
|
||||
return description.add('is nullable type named "$name"');
|
||||
}
|
||||
|
||||
@override
|
||||
bool matches(item, Map matchState) {
|
||||
var type = item is TypeContext ? item : parseType(item);
|
||||
if (type.typeName == null) return false;
|
||||
var result = type.typeName.name == name;
|
||||
return result && type.isNullable == !(nonNull == true);
|
||||
}
|
||||
}
|
|
@ -5,39 +5,39 @@ import 'common.dart';
|
|||
|
||||
main() {
|
||||
test('boolean', () {
|
||||
expect('true', equalsParsed(true));
|
||||
expect('false', equalsParsed(false));
|
||||
expect('true', isValue(true));
|
||||
expect('false', isValue(false));
|
||||
});
|
||||
|
||||
test('number', () {
|
||||
expect('1', equalsParsed(1));
|
||||
expect('1.0', equalsParsed(1.0));
|
||||
expect('-1', equalsParsed(-1));
|
||||
expect('-1.0', equalsParsed(-1.0));
|
||||
expect('6.26e-34', equalsParsed(6.26 * math.pow(10, -34)));
|
||||
expect('-6.26e-34', equalsParsed(-6.26 * math.pow(10, -34)));
|
||||
expect('-6.26e34', equalsParsed(-6.26 * math.pow(10, 34)));
|
||||
expect('1', isValue(1));
|
||||
expect('1.0', isValue(1.0));
|
||||
expect('-1', isValue(-1));
|
||||
expect('-1.0', isValue(-1.0));
|
||||
expect('6.26e-34', isValue(6.26 * math.pow(10, -34)));
|
||||
expect('-6.26e-34', isValue(-6.26 * math.pow(10, -34)));
|
||||
expect('-6.26e34', isValue(-6.26 * math.pow(10, 34)));
|
||||
});
|
||||
|
||||
test('array', () {
|
||||
expect('[]', equalsParsed([]));
|
||||
expect('[1,2]', equalsParsed([1, 2]));
|
||||
expect('[1,2, 3]', equalsParsed([1, 2, 3]));
|
||||
expect('["a"]', equalsParsed(['a']));
|
||||
expect('[]', isValue([]));
|
||||
expect('[1,2]', isValue([1, 2]));
|
||||
expect('[1,2, 3]', isValue([1, 2, 3]));
|
||||
expect('["a"]', isValue(['a']));
|
||||
});
|
||||
|
||||
test('string', () {
|
||||
expect('""', equalsParsed(''));
|
||||
expect('"a"', equalsParsed('a'));
|
||||
expect('"abc"', equalsParsed('abc'));
|
||||
expect('"\\""', equalsParsed('"'));
|
||||
expect('"\\b"', equalsParsed('\b'));
|
||||
expect('"\\f"', equalsParsed('\f'));
|
||||
expect('"\\n"', equalsParsed('\n'));
|
||||
expect('"\\r"', equalsParsed('\r'));
|
||||
expect('"\\t"', equalsParsed('\t'));
|
||||
expect('"\\u0123"', equalsParsed('\u0123'));
|
||||
expect('"\\u0123\\u4567"', equalsParsed('\u0123\u4567'));
|
||||
expect('""', isValue(''));
|
||||
expect('"a"', isValue('a'));
|
||||
expect('"abc"', isValue('abc'));
|
||||
expect('"\\""', isValue('"'));
|
||||
expect('"\\b"', isValue('\b'));
|
||||
expect('"\\f"', isValue('\f'));
|
||||
expect('"\\n"', isValue('\n'));
|
||||
expect('"\\r"', isValue('\r'));
|
||||
expect('"\\t"', isValue('\t'));
|
||||
expect('"\\u0123"', isValue('\u0123'));
|
||||
expect('"\\u0123\\u4567"', isValue('\u0123\u4567'));
|
||||
});
|
||||
|
||||
test('exceptions', () {
|
||||
|
@ -46,21 +46,20 @@ main() {
|
|||
}
|
||||
|
||||
ValueContext parseValue(String text) => parse(text).parseValue();
|
||||
Matcher equalsParsed(value) => new _EqualsParsed(value);
|
||||
Matcher isValue(value) => new _IsValue(value);
|
||||
|
||||
class _EqualsParsed extends Matcher {
|
||||
class _IsValue extends Matcher {
|
||||
final value;
|
||||
|
||||
_EqualsParsed(this.value);
|
||||
_IsValue(this.value);
|
||||
|
||||
@override
|
||||
Description describe(Description description) =>
|
||||
description.add('equals $value when parsed as a GraphQL value');
|
||||
|
||||
@override
|
||||
bool matches(String item, Map matchState) {
|
||||
var p = parse(item);
|
||||
var v = p.parseValue();
|
||||
bool matches(item, Map matchState) {
|
||||
var v = item is ValueContext ? item : parseValue(item);
|
||||
return equals(value).matches(v.value, matchState);
|
||||
}
|
||||
}
|
||||
|
|
75
test/variable_definition_test.dart
Normal file
75
test/variable_definition_test.dart
Normal file
|
@ -0,0 +1,75 @@
|
|||
import 'package:graphql_parser/graphql_parser.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'common.dart';
|
||||
import 'type_test.dart';
|
||||
import 'value_test.dart';
|
||||
|
||||
main() {
|
||||
test('no default value', () {
|
||||
expect(r'$foo: bar',
|
||||
isVariableDefinition('foo', type: isType('bar', isNullable: true)));
|
||||
});
|
||||
|
||||
test('default value', () {
|
||||
expect(
|
||||
r'$foo: int! = 2',
|
||||
isVariableDefinition('foo',
|
||||
type: isType('int', isNullable: false), defaultValue: isValue(2)));
|
||||
});
|
||||
|
||||
test('exceptions', () {
|
||||
expect(() => parseVariableDefinition(r'$foo'), throwsSyntaxError);
|
||||
expect(() => parseVariableDefinition(r'$foo:'), throwsSyntaxError);
|
||||
expect(() => parseVariableDefinition(r'$foo: int ='), throwsSyntaxError);
|
||||
});
|
||||
}
|
||||
|
||||
VariableDefinitionContext parseVariableDefinition(String text) =>
|
||||
parse(text).parseVariableDefinition();
|
||||
|
||||
Matcher isVariableDefinition(String name,
|
||||
{Matcher type, Matcher defaultValue}) =>
|
||||
new _IsVariableDefinition(name, type, defaultValue);
|
||||
|
||||
class _IsVariableDefinition extends Matcher {
|
||||
final String name;
|
||||
final Matcher type, defaultValue;
|
||||
|
||||
_IsVariableDefinition(this.name, this.type, this.defaultValue);
|
||||
|
||||
@override
|
||||
Description describe(Description description) {
|
||||
var desc = description.add('is variable definition with name "$name"');
|
||||
|
||||
if (type != null) {
|
||||
desc = type.describe(desc.add(' with type that '));
|
||||
}
|
||||
|
||||
if (defaultValue != null) {
|
||||
desc = type.describe(desc.add(' with default value that '));
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
@override
|
||||
bool matches(item, Map matchState) {
|
||||
var def = item is VariableDefinitionContext
|
||||
? item
|
||||
: parseVariableDefinition(item);
|
||||
if (def == null) return false;
|
||||
if (def.variable.name != name) return false;
|
||||
bool result = true;
|
||||
|
||||
if (type != null) {
|
||||
result == result && type.matches(def.type, matchState);
|
||||
}
|
||||
|
||||
if (defaultValue != null) {
|
||||
result =
|
||||
result && defaultValue.matches(def.defaultValue.value, matchState);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue