Skip to content

Commit

Permalink
fix(flutter): Query.didUpdateWidget and policy overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
nivekz committed Apr 13, 2020
1 parent 80d9599 commit 32f6172
Show file tree
Hide file tree
Showing 2 changed files with 234 additions and 1 deletion.
8 changes: 7 additions & 1 deletion packages/graphql_flutter/lib/src/widgets/query.dart
Expand Up @@ -72,7 +72,13 @@ class QueryState extends State<Query> {
void didUpdateWidget(Query oldWidget) {
super.didUpdateWidget(oldWidget);

if (!observableQuery.options.areEqualTo(_options)) {
final GraphQLClient client = GraphQLProvider.of(context).value;

final optionsWithOverrides = _options;
optionsWithOverrides.policies = client.defaultPolicies.watchQuery
.withOverrides(optionsWithOverrides.policies);

if (!observableQuery.options.areEqualTo(optionsWithOverrides)) {
_initQuery();
}
}
Expand Down
227 changes: 227 additions & 0 deletions packages/graphql_flutter/test/widgets/query_test.dart
@@ -0,0 +1,227 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:graphql_flutter/src/widgets/query.dart';
import 'package:http/http.dart';
import 'package:mockito/mockito.dart';

class MockHttpClient extends Mock implements Client {}

final query = gql("""
query Foo {
foo
}
""");

class Page extends StatefulWidget {
final Map<String, dynamic> variables;
final FetchPolicy fetchPolicy;
final ErrorPolicy errorPolicy;

Page({
Key key,
this.variables,
this.fetchPolicy,
this.errorPolicy,
}): super(key: key);

@override
State<StatefulWidget> createState() => PageState();
}

class PageState extends State<Page> {
Map<String, dynamic> variables;
FetchPolicy fetchPolicy;
ErrorPolicy errorPolicy;

@override
void initState() {
super.initState();
variables = widget.variables;
fetchPolicy = widget.fetchPolicy;
errorPolicy = widget.errorPolicy;
}

setVariables(Map<String, dynamic> newVariables) {
setState(() {
variables = newVariables;
});
}

setFetchPolicy(FetchPolicy newFetchPolicy) {
setState(() {
fetchPolicy = newFetchPolicy;
});
}

setErrorPolicy(ErrorPolicy newErrorPolicy) {
setState(() {
errorPolicy = newErrorPolicy;
});
}

@override
Widget build(BuildContext context) {
return Query(
options: QueryOptions(
documentNode: query,
variables: variables,
fetchPolicy: fetchPolicy,
errorPolicy: errorPolicy,
),
builder: (QueryResult result, {
Refetch refetch,
FetchMore fetchMore
}) => Container(),
);
}
}

void main() {
group('Query', () {
MockHttpClient mockHttpClient;
HttpLink httpLink;
ValueNotifier<GraphQLClient> client;

setUp(() async {
mockHttpClient = MockHttpClient();
httpLink = HttpLink(
uri: 'https://unused/graphql',
httpClient: mockHttpClient,
);
client = ValueNotifier(
GraphQLClient(
cache: InMemoryCache(storagePrefix: 'test'),
link: httpLink,
),
);
});

testWidgets('does not issue network request on same options',
(WidgetTester tester) async {
final page = Page(
variables: {
'foo': 1,
},
fetchPolicy: FetchPolicy.networkOnly,
errorPolicy: ErrorPolicy.ignore,
);

await tester.pumpWidget(GraphQLProvider(
client: client,
child: page,
));

verify(mockHttpClient.send(any)).called(1);

tester.state<PageState>(find.byWidget(page))
..setVariables({'foo': 1})
..setFetchPolicy(FetchPolicy.networkOnly)
..setErrorPolicy(ErrorPolicy.ignore);
await tester.pump();
verifyNoMoreInteractions(mockHttpClient);
});

testWidgets('does not issue network request when policies stays null',
(WidgetTester tester) async {
final page = Page(
variables: {
'foo': 1,
},
);

await tester.pumpWidget(GraphQLProvider(
client: client,
child: page,
));

verify(mockHttpClient.send(any)).called(1);

tester.state<PageState>(find.byWidget(page))
..setFetchPolicy(null)
..setErrorPolicy(null);
await tester.pump();
verifyNoMoreInteractions(mockHttpClient);
});

testWidgets('issues a new network request when variables change',
(WidgetTester tester) async {
final page = Page(
variables: {
'foo': 1,
},
);

await tester.pumpWidget(GraphQLProvider(
client: client,
child: page,
));

verify(mockHttpClient.send(any)).called(1);

tester.state<PageState>(find.byWidget(page))
.setVariables({'foo': 2});
await tester.pump();
verify(mockHttpClient.send(any)).called(1);
});

testWidgets('issues a new network request when fetch policy changes',
(WidgetTester tester) async {
final page = Page(
fetchPolicy: FetchPolicy.networkOnly,
);

await tester.pumpWidget(GraphQLProvider(
client: client,
child: page,
));

verify(mockHttpClient.send(any)).called(1);

tester.state<PageState>(find.byWidget(page))
.setFetchPolicy(FetchPolicy.cacheFirst);
await tester.pump();
verify(mockHttpClient.send(any)).called(1);
});

testWidgets('issues a new network request when error policy changes',
(WidgetTester tester) async {
final page = Page(
errorPolicy: ErrorPolicy.all,
);

await tester.pumpWidget(GraphQLProvider(
client: client,
child: page,
));

verify(mockHttpClient.send(any)).called(1);

tester.state<PageState>(find.byWidget(page))
.setErrorPolicy(ErrorPolicy.none);
await tester.pump();
verify(mockHttpClient.send(any)).called(1);
});

testWidgets('does not issues new network request when policies are effectively unchanged',
(WidgetTester tester) async {
final page = Page(
fetchPolicy: FetchPolicy.cacheAndNetwork,
errorPolicy: null,
);

await tester.pumpWidget(GraphQLProvider(
client: client,
child: page,
));

verify(mockHttpClient.send(any)).called(1);

tester.state<PageState>(find.byWidget(page))
..setFetchPolicy(null)
..setErrorPolicy(ErrorPolicy.none);
await tester.pump();
verifyNoMoreInteractions(mockHttpClient);
});
});
}

0 comments on commit 32f6172

Please sign in to comment.