Skip to content

Commit

Permalink
More work.
Browse files Browse the repository at this point in the history
  • Loading branch information
brianquinlan committed Nov 2, 2023
1 parent f4d008a commit 5770657
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 25 deletions.
19 changes: 16 additions & 3 deletions pkgs/flutter_http_example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,25 @@ import 'dart:convert';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:provider/provider.dart';

import 'book.dart';
import 'http_client_factory.dart'
if (dart.library.html) 'http_client_factory_web.dart' as http_factory;

void main() {
runWithClient(() => runApp(const BookSearchApp()), http_factory.httpClient);
// Some plugins may offer a way to inject a `package:http` `Client` so
// use `runWithClient` to control the `Client` that they use.
//
// `runWithClient` is not sufficient, however, because flutter tests do
// not preserve the `Zone` used as part of the `runWithClient`
// implementation. See https://github.com/flutter/flutter/issues/96939.
runWithClient(
() => runApp(Provider<Client>(
create: (_) => http_factory.httpClient(),
child: const BookSearchApp(),
dispose: (_, client) => client.close())),
http_factory.httpClient);
}

class BookSearchApp extends StatelessWidget {
Expand All @@ -38,24 +50,25 @@ class HomePage extends StatefulWidget {
class _HomePageState extends State<HomePage> {
List<Book>? _books;
String? _lastQuery;
late Client _client;

@override
void initState() {
super.initState();
_client = context.read<Client>();
}

// Get the list of books matching `query`.
// The `get` call will automatically use the `client` configurated in `main`.
Future<List<Book>> _findMatchingBooks(String query) async {
final response = await get(
final response = await _client.get(
Uri.https(
'www.googleapis.com',
'/books/v1/volumes',
{'q': query, 'maxResults': '1', 'printType': 'books'},
),
);

print(utf8.decode(response.bodyBytes));
final json = jsonDecode(utf8.decode(response.bodyBytes)) as Map;
return Book.listFromJson(json);
}
Expand Down
1 change: 1 addition & 0 deletions pkgs/flutter_http_example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies:
flutter:
sdk: flutter
http: ^0.13.5
provider: ^6.0.5

dev_dependencies:
dart_flutter_team_lints: ^1.0.0
Expand Down
46 changes: 24 additions & 22 deletions pkgs/flutter_http_example/test/widget_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,60 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:flutter_http_example/main.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http/http.dart';
import 'package:http/testing.dart';
import 'package:provider/provider.dart';

const _singleBookResponse = '''
{
"kind": "books#volumes",
"totalItems": 2069,
"items": [
{
"kind": "books#volume",
"id": "gcnAEAAAQBAJ",
"etag": "8yZ12V0pNUI",
"selfLink": "https://www.googleapis.com/books/v1/volumes/gcnAEAAAQBAJ",
"volumeInfo": {
"title": "Flutter Cookbook",
"subtitle": "100+ step-by-step recipes for building cross...",
"authors": [
"Simone Alessandria"
],
"publisher": "Packt Publishing Ltd",
"publishedDate": "2023-05-31",
"description": "Write, test, and publish your web, desktop...",
}]
"imageLinks": {
"smallThumbnail": "http://books.google.com/books/content?id=gcnAEAAAQBAJ&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api"
}
}
}
]
}
''';

void main() {
Widget app(Client client) =>
Provider<Client>(create: (_) => client, child: const BookSearchApp());

testWidgets('Test initial load', (WidgetTester tester) async {
await tester.pumpWidget(const BookSearchApp());
final mockClient = MockClient(
(request) async => throw StateError('unexpected HTTP request'));

await tester.pumpWidget(app(mockClient));

expect(find.text('Please enter a query'), findsOneWidget);
});

testWidgets('Test search', (WidgetTester tester) async {
final mockClient = MockClient((request) async {
if (request.url.path != '/books/v1/volumes') {
if (request.url.path != '/books/v1/volumes' &&
request.url.queryParameters['q'] != 'Flutter') {
return Response('', 404);
}
return Response(_singleBookResponse, 200);
});

// `runWithClient` doesn't work because `pumpWidget` does not
// preserve the `Zone`.
await runWithClient(
() => tester.pumpWidget(const BookSearchApp()), () => mockClient);
await tester.enterText(find.byType(TextField), 'Flutter Cookbook');
await tester.pumpWidget(app(mockClient));
await tester.enterText(find.byType(TextField), 'Flutter');
await tester.pump();

// The book title.
expect(find.text('Flutter Cookbook'), findsOneWidget);
expect(find.text('Write, test, and publish your web, desktop...'),
// The book description.
expect(
find.text('Write, test, and publish your web, desktop...',
skipOffstage: false),
findsOneWidget);
});
}

0 comments on commit 5770657

Please sign in to comment.