Skip to content

Commit

Permalink
feat(client): add error link
Browse files Browse the repository at this point in the history
  • Loading branch information
jayjun committed Oct 26, 2019
1 parent 9858886 commit 873ce2d
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 0 deletions.
21 changes: 21 additions & 0 deletions packages/graphql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,27 @@ if (isStarrred) {
...
```

## Links

### `ErrorLink`

Perform custom logic when a GraphQL or network error happens, such as logging or
signing out.

```dart
final ErrorLink errorLink = ErrorLink(errorHandler: (response) {
if (response.graphQLErrors != null) {
for (var error in response.graphQLErrors) {
print('[GraphQL error]: Message: ${error['message']}, Location: ${error['locations']}, Path: ${error['path']}');
}
}
if (response.networkError != null) {
print('[Network error]: ${response.networkError}');
}
});
```

[build-status-badge]: https://img.shields.io/circleci/build/github/zino-app/graphql-flutter.svg?style=flat-square
[build-status-link]: https://circleci.com/gh/zino-app/graphql-flutter
[coverage-badge]: https://img.shields.io/codecov/c/github/zino-app/graphql-flutter.svg?style=flat-square
Expand Down
1 change: 1 addition & 0 deletions packages/graphql/lib/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export 'package:graphql/src/core/query_result.dart';
export 'package:graphql/src/exceptions/exceptions.dart';

export 'package:graphql/src/link/auth/link_auth.dart';
export 'package:graphql/src/link/error/link_error.dart';
export 'package:graphql/src/link/http/link_http.dart';
export 'package:graphql/src/link/link.dart';
export 'package:graphql/src/link/web_socket/link_web_socket.dart';
Expand Down
63 changes: 63 additions & 0 deletions packages/graphql/lib/src/link/error/link_error.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import 'dart:async';

import 'package:graphql/src/link/link.dart';
import 'package:graphql/src/link/operation.dart';
import 'package:graphql/src/link/fetch_result.dart';

typedef ErrorHandler = void Function(ErrorResponse);

class ErrorResponse {
ErrorResponse({
this.graphQLErrors,
this.networkError,
this.result,
this.operation,
this.forward,
});

List<dynamic> graphQLErrors;
Exception networkError;
FetchResult result;
Operation operation;
NextLink forward;
}

class ErrorLink extends Link {
ErrorLink({
this.errorHandler,
}) : super(
request: (Operation operation, [NextLink forward]) {
StreamController<FetchResult> controller;

Future<void> onListen() async {
Stream stream = forward(operation).map((FetchResult result) {
if (result.errors != null) {
errorHandler(ErrorResponse(
graphQLErrors: result.errors,
result: result,
operation: operation,
forward: forward,
));
}
return result;
}).handleError((error) {
errorHandler(ErrorResponse(
networkError: error,
operation: operation,
forward: forward,
));
throw error;
});

await controller.addStream(stream);
await controller.close();
}

controller = StreamController<FetchResult>(onListen: onListen);

return controller.stream;
},
);

ErrorHandler errorHandler;
}
109 changes: 109 additions & 0 deletions packages/graphql/test/link/error/link_error_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import "dart:async";
import "dart:convert";

import 'package:graphql/src/exceptions/exceptions.dart';
import 'package:graphql/src/link/error/link_error.dart';
import 'package:graphql/src/link/http/link_http.dart';
import 'package:graphql/src/link/link.dart';
import 'package:graphql/src/link/operation.dart';
import "package:http/http.dart" as http;
import "package:mockito/mockito.dart";
import "package:test/test.dart";

class MockClient extends Mock implements http.Client {}

void main() {
group('error link', () {
MockClient client;
Operation query;
HttpLink httpLink;

setUp(() {
client = MockClient();
query = Operation(
document: 'query Operation {}',
operationName: 'Operation',
);
httpLink = HttpLink(
uri: '/graphql-test',
httpClient: client,
);
});

test('network error', () async {
bool called = false;

when(
client.send(any),
).thenAnswer(
(_) => Future.value(
http.StreamedResponse(
Stream.fromIterable(
[utf8.encode('{}')],
),
400,
),
),
);

final errorLink = ErrorLink(errorHandler: (response) {
if (response.networkError != null) {
called = true;
}
});

Exception exception;

try {
await execute(
link: errorLink.concat(httpLink),
operation: query,
).first;
} on Exception catch (e) {
exception = e;
}

expect(
exception,
const TypeMatcher<ClientException>(),
);
expect(
called,
true,
);
});

test('graphql error', () async {
bool called = false;

when(
client.send(any),
).thenAnswer(
(_) => Future.value(
http.StreamedResponse(
Stream.fromIterable(
[utf8.encode('{"errors":[{"message":"error"}]}')],
),
200,
),
),
);

final errorLink = ErrorLink(errorHandler: (response) {
if (response.graphQLErrors != null) {
called = true;
}
});

await execute(
link: errorLink.concat(httpLink),
operation: query,
).first;

expect(
called,
true,
);
});
});
}

0 comments on commit 873ce2d

Please sign in to comment.