diff --git a/.idea/runConfigurations/objects_in_equality_test_dart.xml b/.idea/runConfigurations/objects_in_equality_test_dart.xml
new file mode 100644
index 00000000..47dbf8c5
--- /dev/null
+++ b/.idea/runConfigurations/objects_in_equality_test_dart.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/tests_in_graphql_schema.xml b/.idea/runConfigurations/tests_in_graphql_schema.xml
new file mode 100644
index 00000000..b3d4f5e6
--- /dev/null
+++ b/.idea/runConfigurations/tests_in_graphql_schema.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/graphql_schema/lib/src/field.dart b/graphql_schema/lib/src/field.dart
index 053b4604..4132e68b 100644
--- a/graphql_schema/lib/src/field.dart
+++ b/graphql_schema/lib/src/field.dart
@@ -17,8 +17,8 @@ class GraphQLObjectField {
this.deprecationReason,
this.description}) {
assert(type != null, 'GraphQL fields must specify a `type`.');
- assert(
- resolve != null, 'GraphQL fields must specify a `resolve` callback.');
+// assert(
+// resolve != null, 'GraphQL fields must specify a `resolve` callback.');
this.inputs.addAll(arguments ?? []);
}
diff --git a/graphql_schema/lib/src/gen.dart b/graphql_schema/lib/src/gen.dart
index d8044e65..8a2474e5 100644
--- a/graphql_schema/lib/src/gen.dart
+++ b/graphql_schema/lib/src/gen.dart
@@ -24,7 +24,7 @@ GraphQLObjectField field(
String deprecationReason, String description}) {
return new GraphQLObjectField(name, type,
arguments: inputs,
- resolve: resolve ?? (_, __) => null,
+ resolve: resolve,
description: description,
deprecationReason: deprecationReason);
}
diff --git a/graphql_schema/lib/src/union.dart b/graphql_schema/lib/src/union.dart
index 129f985b..5253ac27 100644
--- a/graphql_schema/lib/src/union.dart
+++ b/graphql_schema/lib/src/union.dart
@@ -34,7 +34,9 @@ class GraphQLUnionType
Map serialize(Map value) {
for (var type in possibleTypes) {
try {
- return type.serialize(value);
+ if (type.validate('@root', value).successful) {
+ return type.serialize(value);
+ }
} catch (_) {}
}
diff --git a/graphql_schema/test/equality_test.dart b/graphql_schema/test/equality_test.dart
new file mode 100644
index 00000000..a5fb2e70
--- /dev/null
+++ b/graphql_schema/test/equality_test.dart
@@ -0,0 +1,113 @@
+import 'package:graphql_schema/graphql_schema.dart';
+import 'package:test/test.dart';
+
+/// Note: this doesn't test for scalar types, which are final, and therefore use built-in equality.
+void main() {
+ group('equality', () {
+ test('enums', () {
+ expect(enumTypeFromStrings('A', ['B', 'C']),
+ enumTypeFromStrings('A', ['B', 'C']));
+ expect(enumTypeFromStrings('A', ['B', 'C']),
+ isNot(enumTypeFromStrings('B', ['B', 'C'])));
+ });
+
+ test('objects', () {
+ expect(
+ objectType('B', fields: [
+ field('b', graphQLString.nonNullable()),
+ ]),
+ objectType('B', fields: [
+ field('b', graphQLString.nonNullable()),
+ ]),
+ );
+
+ expect(
+ objectType('B', fields: [
+ field('b', graphQLString.nonNullable()),
+ ]),
+ isNot(objectType('BD', fields: [
+ field('b', graphQLString.nonNullable()),
+ ])),
+ );
+
+ expect(
+ objectType('B', fields: [
+ field('b', graphQLString.nonNullable()),
+ ]),
+ isNot(objectType('B', fields: [
+ field('ba', graphQLString.nonNullable()),
+ ])),
+ );
+
+ expect(
+ objectType('B', fields: [
+ field('b', graphQLString.nonNullable()),
+ ]),
+ isNot(objectType('B', fields: [
+ field('a', graphQLFloat.nonNullable()),
+ ])),
+ );
+ });
+
+ test('input type', () {});
+
+ test('union type', () {
+ expect(
+ new GraphQLUnionType('A', [
+ objectType('B', fields: [
+ field('b', graphQLString.nonNullable()),
+ ]),
+ objectType('C', fields: [
+ field('c', graphQLString.nonNullable()),
+ ]),
+ ]),
+ new GraphQLUnionType('A', [
+ objectType('B', fields: [
+ field('b', graphQLString.nonNullable()),
+ ]),
+ objectType('C', fields: [
+ field('c', graphQLString.nonNullable()),
+ ]),
+ ]),
+ );
+
+ expect(
+ new GraphQLUnionType('A', [
+ objectType('B', fields: [
+ field('b', graphQLString.nonNullable()),
+ ]),
+ objectType('C', fields: [
+ field('c', graphQLString.nonNullable()),
+ ]),
+ ]),
+ isNot(new GraphQLUnionType('AA', [
+ objectType('B', fields: [
+ field('b', graphQLString.nonNullable()),
+ ]),
+ objectType('C', fields: [
+ field('c', graphQLString.nonNullable()),
+ ]),
+ ])),
+ );
+
+ expect(
+ new GraphQLUnionType('A', [
+ objectType('BB', fields: [
+ field('b', graphQLString.nonNullable()),
+ ]),
+ objectType('C', fields: [
+ field('c', graphQLString.nonNullable()),
+ ]),
+ ]),
+ isNot(new GraphQLUnionType('AA', [
+ objectType('BDD', fields: [
+ field('b', graphQLString.nonNullable()),
+ ]),
+ objectType('C', fields: [
+ field('c', graphQLString.nonNullable()),
+ ]),
+ ])),
+ );
+ });
+ });
+}
diff --git a/graphql_schema/test/inheritance_test.dart b/graphql_schema/test/inheritance_test.dart
new file mode 100644
index 00000000..0157bcfa
--- /dev/null
+++ b/graphql_schema/test/inheritance_test.dart
@@ -0,0 +1,67 @@
+import 'package:graphql_schema/graphql_schema.dart';
+import 'package:test/test.dart';
+
+void main() {
+ group('interface', () {
+ var a = objectType(
+ 'A',
+ isInterface: true,
+ fields: [
+ field('text', graphQLString.nonNullable()),
+ ],
+ );
+
+ var b = objectType(
+ 'B',
+ isInterface: true,
+ interfaces: [a],
+ fields: [
+ field('text', graphQLString.nonNullable()),
+ ],
+ );
+
+ var c = objectType(
+ 'C',
+ isInterface: true,
+ interfaces: [b],
+ fields: [
+ field('text', graphQLString.nonNullable()),
+ ],
+ );
+
+ test('child implements parent', () {
+ expect(b.isImplementationOf(a), true);
+ expect(c.isImplementationOf(b), true);
+ });
+
+ test('parent does not implement child', () {
+ expect(a.isImplementationOf(b), false);
+ });
+
+ test('child interfaces contains parent', () {
+ expect(b.interfaces, contains(a));
+ expect(c.interfaces, contains(b));
+ });
+
+ test('parent possibleTypes contains child', () {
+ expect(a.possibleTypes, contains(b));
+ expect(b.possibleTypes, contains(c));
+ });
+
+ test('grandchild implements grandparent', () {
+ expect(c.isImplementationOf(a), true);
+ });
+
+ test('grandparent does not implement grandchild', () {
+ expect(a.isImplementationOf(c), false);
+ });
+
+ test('grandchild interfaces contains grandparent', () {
+ expect(c.interfaces, contains(a));
+ });
+
+ test('grandparent possibleTypes contains grandchild', () {
+ expect(a.possibleTypes, contains(c));
+ });
+ });
+}
\ No newline at end of file
diff --git a/graphql_schema/test/serialize_test.dart b/graphql_schema/test/serialize_test.dart
index c3c0efe7..5725df02 100644
--- a/graphql_schema/test/serialize_test.dart
+++ b/graphql_schema/test/serialize_test.dart
@@ -1,11 +1,36 @@
import 'package:graphql_schema/graphql_schema.dart';
import 'package:test/test.dart';
+
import 'common.dart';
main() {
- test('scalar', () {
- expect(graphQLString.serialize('a'), 'a');
+ test('int', () {
+ expect(graphQLInt.serialize(23), 23);
+ });
+ test('float', () {
+ expect(graphQLFloat.serialize(23.0), 23.0);
+ });
+
+ test('bool', () {
+ expect(graphQLBoolean.serialize(true), true);
+ });
+
+ test('string', () {
+ expect(graphQLString.serialize('a'), 'a');
+ });
+
+ test('enum', () {
+ var response = enumTypeFromStrings('Response', ['YES', 'NO']);
+ expect(response.serialize('YES'), 'YES');
+ });
+
+ test('enum only serializes correct values', () {
+ var response = enumTypeFromStrings('Response', ['YES', 'NO']);
+ expect(() => response.serialize('MAYBE'), throwsStateError);
+ });
+
+ test('date', () {
var now = new DateTime.now();
expect(graphQLDate.serialize(now), now.toIso8601String());
});
@@ -19,6 +44,21 @@ main() {
[today.toIso8601String(), tomorrow.toIso8601String()]);
});
+ group('input object', () {
+ var type = inputObjectType(
+ 'Foo',
+ inputFields: [
+ inputField('bar', graphQLString.nonNullable()),
+ inputField('baz', graphQLFloat.nonNullable()),
+ ],
+ );
+
+ test('serializes valid input', () {
+ expect(
+ type.serialize({'bar': 'a', 'baz': 2.0}), {'bar': 'a', 'baz': 2.0});
+ });
+ });
+
test('object', () {
var catchDate = new DateTime.now();
@@ -28,6 +68,37 @@ main() {
{'species': 'Pikachu', 'catch_date': catchDate.toIso8601String()});
});
+ test('union type lets any of its types serialize', () {
+ var typeType = enumTypeFromStrings('Type', [
+ 'FIRE',
+ 'WATER',
+ 'GRASS',
+ ]);
+
+ var pokemonType = objectType('Pokémon', fields: [
+ field(
+ 'name',
+ graphQLString.nonNullable(),
+ ),
+ field(
+ 'type',
+ typeType,
+ ),
+ ]);
+
+ var digimonType = objectType(
+ 'Digimon',
+ fields: [
+ field('size', graphQLFloat.nonNullable()),
+ ],
+ );
+
+ var u = new GraphQLUnionType('Monster', [pokemonType, digimonType]);
+
+ expect(u.serialize({'size': 10.0}), {'size': 10.0});
+ expect(u.serialize({'name': 'Charmander', 'type': 'FIRE'}), {'name': 'Charmander', 'type': 'FIRE'});
+ });
+
test('nested object', () {
var pikachuDate = new DateTime.now(),
charizardDate = pikachuDate.subtract(new Duration(days: 10));
diff --git a/graphql_schema/test/validation_test.dart b/graphql_schema/test/validation_test.dart
index f8810d2d..d858a75a 100644
--- a/graphql_schema/test/validation_test.dart
+++ b/graphql_schema/test/validation_test.dart
@@ -27,6 +27,10 @@ void main() {
var throwsATypeError =
throwsA(predicate((x) => x is TypeError, 'is a type error'));
+ test('object accepts valid input', () {
+ expect({'name': 'Charmander', 'type': 'FIRE'}, isValidPokemon);
+ });
+
test('mismatched scalar type', () {
expect(() => pokemonType.validate('@root', {'name': 24}), throwsATypeError);
});
@@ -50,4 +54,49 @@ void main() {
test('enum rejects invalid value', () {
expect(typeType.validate('@root', 'POISON').successful, false);
});
+
+ group('union type', () {
+ var digimonType = objectType(
+ 'Digimon',
+ fields: [
+ field('size', graphQLFloat.nonNullable()),
+ ],
+ );
+
+ var u = new GraphQLUnionType('Monster', [pokemonType, digimonType]);
+
+ test('any of its types returns valid', () {
+ expect(u.validate('@root', {'size': 32.0}).successful, true);
+ expect(
+ u.validate(
+ '@root', {'name': 'Charmander', 'type': 'FIRE'}).successful,
+ true);
+ });
+ });
+
+ group('input object', () {
+ var type = inputObjectType(
+ 'Foo',
+ inputFields: [
+ inputField('bar', graphQLString.nonNullable()),
+ inputField('baz', graphQLFloat.nonNullable()),
+ ],
+ );
+
+ test('accept valid input', () {
+ expect(type.validate('@root', {'bar': 'a', 'baz': 2.0}).value,
+ {'bar': 'a', 'baz': 2.0});
+ });
+
+ test('error on missing non-null fields', () {
+ expect(type.validate('@root', {'bar': 'a'}).successful, false);
+ });
+
+ test('error on unrecognized fields', () {
+ expect(
+ type.validate(
+ '@root', {'bar': 'a', 'baz': 2.0, 'franken': 'stein'}).successful,
+ false);
+ });
+ });
}