-
-
Notifications
You must be signed in to change notification settings - Fork 628
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
graphql_flutter: add integration testing
Signed-off-by: Vincenzo Palazzo <[email protected]>
- Loading branch information
1 parent
466f091
commit bd4491d
Showing
11 changed files
with
353 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
name: "graphql_flutter: integration testing " | ||
on: [push, pull_request] | ||
jobs: | ||
integration_tests: | ||
runs-on: ubuntu-20.04 | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: subosito/flutter-action@v1 | ||
- run: flutter pub get | ||
- run: chromedriver --port=4444 & | ||
- name: graphql_chat intergration testing | ||
run: | | ||
cd packages/graphql_flutter/example/graphql_chat | ||
flutter pub dev | ||
flutter drive --driver=test_driver/integration_test.dart --target=integration_test/intergration_test.dart -d chrome |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
packages/graphql_flutter/example/graphql_chat/integration_test/clients/ClientProvider.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/// Client Provider is a utils class that contains in a single place | ||
/// all the client used to ran the integration testing with all the | ||
/// servers. | ||
/// | ||
/// The test supported in this class for the moment are: | ||
/// - GraphQl Client Chat: https://github.com/vincenzopalazzo/keep-safe-graphql | ||
/// | ||
/// author: https://github.com/vincenzopalazzo | ||
/// ClientProvider is a singleton implementation that contains | ||
/// all the client supported to implement the integration testing. | ||
import 'package:graphql_flutter/graphql_flutter.dart'; | ||
|
||
class ClientProvider { | ||
static ClientProvider? _instance; | ||
|
||
GraphQLClient? _chatApp; | ||
|
||
ClientProvider._internal(); | ||
|
||
factory ClientProvider() { | ||
_instance ??= ClientProvider._internal(); | ||
return _instance!; | ||
} | ||
|
||
/// Init the client regarding the chat app server | ||
/// crete only a single instance of it. | ||
GraphQLClient chatAppClient( | ||
{GraphQLCache? cache, bool forceRecreation = false}) { | ||
if (_chatApp == null || forceRecreation) { | ||
final HttpLink httpLink = HttpLink( | ||
'https://api.chat.graphql-flutter.dev/graphql', | ||
defaultHeaders: { | ||
"Accept": "application/json", | ||
"Access-Control_Allow_Origin": "*", | ||
}, | ||
); | ||
var wsLink = WebSocketLink( | ||
'ws://api.chat.graphql-flutter.dev/graphql', | ||
config: const SocketClientConfig( | ||
inactivityTimeout: Duration(seconds: 40), | ||
), | ||
subProtocol: GraphQLProtocol.graphqlTransportWs, | ||
); | ||
final Link link = httpLink.split( | ||
(request) => request.isSubscription, | ||
wsLink, | ||
httpLink, | ||
); | ||
if (!forceRecreation) { | ||
_chatApp = GraphQLClient(link: link, cache: cache ?? GraphQLCache()); | ||
} else { | ||
return GraphQLClient(link: link, cache: cache ?? GraphQLCache()); | ||
} | ||
} | ||
return _chatApp!; | ||
} | ||
} |
119 changes: 119 additions & 0 deletions
119
packages/graphql_flutter/example/graphql_chat/integration_test/intergration_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
/// Integration test regarding the graphq_flutter widget | ||
/// | ||
/// In this particular test suite we implement a battery of test | ||
/// to make sure that all the operation on a widget are done | ||
/// correctly. | ||
/// | ||
/// More precise in this file all the test are regarding the web socket and | ||
/// the subscription. | ||
/// | ||
/// Trying to reproduce the problems caused by the following issue | ||
/// - Subscription not receive update | ||
/// - https://github.com/zino-hofmann/graphql-flutter/issues/1163 | ||
/// - https://github.com/zino-hofmann/graphql-flutter/issues/1162 | ||
/// | ||
/// author: https://github.com/vincenzopalazzo | ||
import 'package:flutter_test/flutter_test.dart'; | ||
import 'package:graphql_flutter/graphql_flutter.dart'; | ||
import 'package:integration_test/integration_test.dart'; | ||
import 'package:logger/logger.dart'; | ||
import 'clients/ClientProvider.dart'; | ||
import 'model/chat_app_model.dart'; | ||
import 'widget/MockAppView.dart' as app; | ||
import 'widget/list_view_query.dart'; | ||
import 'widget/list_view_subscription.dart'; | ||
|
||
/// Configure the test to check if the ws `GraphQLProtocol.graphqlTransportWs` receive | ||
/// update correctly. | ||
Future<void> configureTestForSimpleSubscriptionUpdate(dynamic tester) async { | ||
var logger = Logger(); | ||
|
||
/// build a simple client with a in memory | ||
var client = ClientProvider().chatAppClient(); | ||
app.main(client: client, childToTest: ListChatSubscriptionView()); | ||
await tester.pumpAndSettle(); | ||
var listChats = await client.query(QueryOptions(document: gql(r""" | ||
query { | ||
getChats { | ||
__typename | ||
id | ||
description | ||
name | ||
} | ||
} | ||
"""))); | ||
logger.d("Exception: ${listChats.exception}"); | ||
expect(listChats.hasException, isFalse); | ||
logger.i("Chats contains inside the server: ${listChats.data}"); | ||
var chatName = "graphql_flutter test chat ${DateTime.now()}"; | ||
var description = "graphql_flutter integration test in ${DateTime.now()}"; | ||
await client.mutate(MutationOptions(document: gql(r""" | ||
mutation CreateChat($description: String!, $name: String!){ | ||
createChat(description: $description, name: $name) { | ||
__typename | ||
name | ||
} | ||
} | ||
"""), variables: { | ||
"name": chatName, | ||
"description": description, | ||
})); | ||
|
||
//find new item in the list | ||
await tester.pump(const Duration(seconds: 10)); | ||
final subscriptionItem = find.text(chatName); | ||
expect(subscriptionItem, findsOneWidget); | ||
} | ||
|
||
/// Configure the test to check if we receive all the element from the graphql | ||
Future<void> configureTestForSimpleQuery(dynamic tester) async { | ||
var logger = Logger(); | ||
|
||
/// build a simple client with a in memory | ||
var client = ClientProvider().chatAppClient(); | ||
app.main(client: client, childToTest: ListChatQueryView()); | ||
await tester.pumpAndSettle(); | ||
await tester.pump(const Duration(seconds: 10)); | ||
var listChats = await client.query(QueryOptions( | ||
document: gql(r""" | ||
query { | ||
getChats { | ||
__typename | ||
id | ||
description | ||
name | ||
} | ||
} | ||
"""), | ||
parserFn: (Map<String, dynamic> json) { | ||
var rawList = List.of(json["getChats"] as List<dynamic>); | ||
return rawList | ||
.map((jsonChat) => Chat.fromJSON(jsonChat as Map<String, dynamic>)) | ||
.toList(); | ||
})); | ||
logger.d("Exception: ${listChats.exception}"); | ||
expect(listChats.hasException, isFalse); | ||
logger.i("Chats contains inside the server: ${listChats.data}"); | ||
var chats = listChats.parsedData as List<Chat>; | ||
for (var chat in chats) { | ||
//find new item in the list | ||
final subscriptionItem = find.text(chat.name); | ||
|
||
/// Finds not only one but more than one | ||
expect(subscriptionItem, findsWidgets); | ||
} | ||
} | ||
|
||
class CustomBindings extends AutomatedTestWidgetsFlutterBinding { | ||
@override | ||
bool get overrideHttpClient => false; | ||
} | ||
|
||
void main() { | ||
//CustomBindings(); | ||
IntegrationTestWidgetsFlutterBinding.ensureInitialized(); | ||
testWidgets('Run simple query and check if we find all the element displayed', | ||
configureTestForSimpleQuery); | ||
testWidgets('Run simple subscription and wait the result of the update', | ||
configureTestForSimpleSubscriptionUpdate); | ||
} |
14 changes: 14 additions & 0 deletions
14
packages/graphql_flutter/example/graphql_chat/integration_test/model/chat_app_model.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
class Chat { | ||
final int id; | ||
final String name; | ||
final String description; | ||
|
||
const Chat({required this.id, required this.name, required this.description}); | ||
|
||
factory Chat.fromJSON(Map<String, dynamic> json) { | ||
return Chat( | ||
id: json["id"] as int, | ||
name: json["name"].toString(), | ||
description: json["description"].toString()); | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
packages/graphql_flutter/example/graphql_chat/integration_test/widget/MockAppView.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:graphql_flutter/graphql_flutter.dart'; | ||
|
||
void main({GraphQLClient? client, Widget? childToTest}) => runApp( | ||
MockAppView(client: ValueNotifier(client!), childToTest: childToTest!)); | ||
|
||
class MockAppView extends StatelessWidget { | ||
final ValueNotifier<GraphQLClient> client; | ||
final Widget childToTest; | ||
|
||
MockAppView({required this.client, required this.childToTest}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return GraphQLProvider( | ||
client: client, | ||
child: MaterialApp( | ||
title: 'Mock App', | ||
home: childToTest, | ||
), | ||
); | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
packages/graphql_flutter/example/graphql_chat/integration_test/widget/list_view_query.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/// ListView flutter Widget implementation to display all the information | ||
/// of the chats that are created by by the client chat app. | ||
/// | ||
/// author: https://github.com/vincenzopalazzo | ||
import 'package:flutter/material.dart'; | ||
import 'package:graphql_flutter/graphql_flutter.dart'; | ||
import 'package:logger/logger.dart'; | ||
|
||
import '../model/chat_app_model.dart'; | ||
|
||
class ListChatQueryView extends StatelessWidget { | ||
/// N.B: Please to not use this approach in a dev environment but | ||
/// consider to use code generator or put the query content somewhere else. | ||
String query = r""" | ||
query { | ||
getChats { | ||
__typename | ||
id | ||
description | ||
name | ||
} | ||
} | ||
"""; | ||
Logger _logger = Logger(); | ||
List<Chat> _chats = []; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Query( | ||
options: QueryOptions<List<Chat>>( | ||
fetchPolicy: FetchPolicy.networkOnly, | ||
parserFn: (Map<String, dynamic> json) { | ||
var rawList = List.of(json["getChats"] as List<dynamic>); | ||
return rawList | ||
.map((jsonChat) => | ||
Chat.fromJSON(Map.from(jsonChat as Map<String, dynamic>))) | ||
.toList(); | ||
}, | ||
document: gql(query)), | ||
builder: (QueryResult result, | ||
{VoidCallback? refetch, FetchMore? fetchMore}) { | ||
if (result.hasException) { | ||
_logger.e(result.exception); | ||
throw Exception(result.exception); | ||
} | ||
if (result.isLoading) { | ||
_logger.i("Still loading"); | ||
return const Text("Loading chats"); | ||
} | ||
_logger.d(result.data ?? "Data is undefined"); | ||
_chats = result.parsedData as List<Chat>; | ||
return ListView( | ||
children: _chats.map((chatData) => Text(chatData.name)).toList(), | ||
); | ||
}); | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
.../graphql_flutter/example/graphql_chat/integration_test/widget/list_view_subscription.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/// ListView flutter Widget implementation to display all the information | ||
/// of the chats that are created by by the client chat app. | ||
/// | ||
/// author: https://github.com/vincenzopalazzo | ||
import 'package:flutter/material.dart'; | ||
import 'package:graphql_flutter/graphql_flutter.dart'; | ||
import 'package:logger/logger.dart'; | ||
|
||
import '../model/chat_app_model.dart'; | ||
|
||
class ListChatSubscriptionView extends StatelessWidget { | ||
/// N.B: Please to not use this approach in a dev environment but | ||
/// consider to use code generator or put the query content somewhere else. | ||
String query = r""" | ||
subscription { | ||
chatCreated { | ||
id | ||
name | ||
description | ||
} | ||
} | ||
"""; | ||
Logger _logger = Logger(); | ||
List<Chat> _chats = []; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Subscription( | ||
options: SubscriptionOptions( | ||
parserFn: (Map<String, dynamic> json) { | ||
return Chat.fromJSON(json["chatCreated"] as Map<String, dynamic>); | ||
}, | ||
document: gql(query), | ||
), | ||
builder: (result) { | ||
if (result.hasException) { | ||
_logger.e(result.exception); | ||
return Text(result.exception.toString()); | ||
} | ||
|
||
if (result.isLoading) { | ||
return const Center( | ||
child: CircularProgressIndicator(), | ||
); | ||
} | ||
// ResultAccumulator is a provided helper widget for collating subscription results. | ||
_logger.d(result.data ?? "Data is undefined"); | ||
var chat = result.parsedData as Chat; | ||
return ResultAccumulator.appendUniqueEntries( | ||
latest: _chats, | ||
builder: (context, {results}) => | ||
ListView(children: [Text(chat.name)]), | ||
); | ||
}); | ||
} | ||
} |
Oops, something went wrong.