Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(fmc): add tests #14

Merged
merged 3 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.x'
channel: "stable"
- name: Build APK
working-directory: example
run: flutter build apk
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,7 @@ pubspec.lock
.dart_tool/
build/
.flutter-plugins
.flutter-plugins-dependencies
.flutter-plugins-dependencies

# ignore coverage info
**/coverage/lcov.info
18 changes: 18 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
codecov:
require_ci_to_pass: true

coverage:
status:
project:
default:
# the required coverage value
target: 0%
# the leniency in hitting the target
threshold: 100%
# completely disable coverage warnings and the status check for changes
patch: off

ignore:
- "**/*.g.dart"
- "**/*.freezed.dart"
- "example"
7 changes: 4 additions & 3 deletions flutter_map_cache/lib/src/cached_image_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class CachedImageProvider extends ImageProvider<CachedImageProvider> {

return MultiFrameImageStreamCompleter(
// ignore: discarded_futures, not actually but the lint thinks so
codec: _loadAsync(key, chunkEvents, decode),
codec: loadAsync(key, chunkEvents, decode),
chunkEvents: chunkEvents.stream,
scale: 1,
debugLabel: url,
Expand All @@ -65,7 +65,8 @@ class CachedImageProvider extends ImageProvider<CachedImageProvider> {
);
}

Future<Codec> _loadAsync(
/// This method does the actual fetching of the image
Future<Codec> loadAsync(
CachedImageProvider key,
StreamController<ImageChunkEvent> chunkEvents,
ImageDecoderCallback decode, {
Expand Down Expand Up @@ -108,7 +109,7 @@ class CachedImageProvider extends ImageProvider<CachedImageProvider> {
// check if no fallback url set
if (fallbackUrl == null) rethrow;
// use fallback url
return _loadAsync(key, chunkEvents, decode, useFallback: true);
return loadAsync(key, chunkEvents, decode, useFallback: true);
}
}
}
5 changes: 5 additions & 0 deletions flutter_map_cache/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,9 @@ dependencies:
flutter_map: ^6.0.0

dev_dependencies:
flutter_test:
sdk: flutter
total_lints: ^3.0.0
test: ^1.24.9
http_mock_adapter: ^0.6.1
latlong2: ^0.9.0
28 changes: 28 additions & 0 deletions flutter_map_cache/test/cached_image_provider_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'dart:async';

import 'package:dio/dio.dart';
import 'package:flutter_map_cache/flutter_map_cache.dart';
import 'package:test/test.dart';

// ignore_for_file: deprecated_member_use_from_same_package

Future<void> main() async {
test('create new instance', () {
final dio = Dio();
const url = 'https://tile.openstreetmap.org/0/0/0.png';
const headers = <String, String>{};
final cancelLoadingFuture = Future<void>.delayed(const Duration(days: 1));

final provider = CachedImageProvider(
dio: dio,
url: url,
headers: headers,
cancelLoading: cancelLoadingFuture,
);

expect(provider.dio, equals(dio));
expect(provider.url, equals(url));
expect(provider.headers, equals(headers));
expect(provider.cancelLoading, equals(cancelLoadingFuture));
});
}
100 changes: 100 additions & 0 deletions flutter_map_cache/test/cached_tile_provider_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import 'package:dio/dio.dart';
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_cache/flutter_map_cache.dart';
import 'package:test/test.dart';

// ignore_for_file: deprecated_member_use_from_same_package

Future<void> main() async {
test('create new instance', () {
final store = MemCacheStore();

final provider = CachedTileProvider(store: store);

expect(provider, isA<TileProvider>());
});
test('check that interceptors contain a DioCacheInterceptor', () {
final store = MemCacheStore();

final provider = CachedTileProvider(store: store);

expect(
provider.dio.interceptors.any((entry) => entry is DioCacheInterceptor),
isTrue,
);
});
test('check that provided interceptors are added', () {
final store = MemCacheStore();
final someInterceptor = LogInterceptor(
logPrint: (object) => debugPrint(object.toString()),
);

final provider = CachedTileProvider(
store: store,
interceptors: [someInterceptor],
);

expect(provider.dio.interceptors, contains(someInterceptor));
final cacheInterceptor = provider.dio.interceptors
.firstWhere((entry) => entry is DioCacheInterceptor);
expect(provider.dio.interceptors, contains(cacheInterceptor));
});
test('provided Dio instance but without BaseOptions', () {
final store = MemCacheStore();
final dio = Dio();

final provider = CachedTileProvider(store: store, dio: dio);

expect(provider.dio, equals(provider.dio));
expect(provider.dio.options, equals(provider.dio.options));
});
test('provided Dio instance and custom BaseOptions', () {
final store = MemCacheStore();
const someBaseUrl = 'https://unique-url.example.com';
final dioOptions = BaseOptions(
baseUrl: someBaseUrl,
headers: {'X-API-TOKEN': 'test123'},
);
final dio = Dio(dioOptions);

final provider = CachedTileProvider(store: store, dio: dio);

expect(provider.dio.options, equals(provider.dio.options));
expect(provider.dio.options.baseUrl, equals(someBaseUrl));
expect(provider.dio.options.headers.length, equals(1));
expect(provider.dio.options.headers['X-API-TOKEN'], equals('test123'));
});
test('use empty dioOptions parameter', () {
final store = MemCacheStore();
final dioOptions = BaseOptions();

final provider = CachedTileProvider(store: store, dioOptions: dioOptions);

expect(provider.dio.options, equals(dioOptions));
expect(provider.dio.options.headers.isEmpty, isTrue);
});
test('use dioOptions parameter with values', () {
final store = MemCacheStore();
const someBaseUrl = 'https://unique-url.example.com';
final dioOptions = BaseOptions(
baseUrl: someBaseUrl,
headers: {'X-API-TOKEN': 'test123'},
);

final provider = CachedTileProvider(store: store, dioOptions: dioOptions);

expect(provider.dio.options, equals(provider.dio.options));
expect(provider.dio.options.baseUrl, equals(someBaseUrl));
expect(provider.dio.options.headers.length, equals(1));
expect(provider.dio.options.headers['X-API-TOKEN'], equals('test123'));
});
test('assert that this tile provider supports tile cancellation', () {
final store = MemCacheStore();

final provider = CachedTileProvider(store: store);

expect(provider.supportsCancelLoading, isTrue);
});
}
14 changes: 14 additions & 0 deletions flutter_map_cache/test/integration_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import 'package:dio/dio.dart';
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:flutter_test/flutter_test.dart';

import 'utils/test_app.dart';

Future<void> main() async {
testWidgets('FlutterMap with CachedTileProvider', (tester) async {
final dio = Dio(); // createDioReturningEmptyTiles();
final cacheStore = MemCacheStore();
await tester.pumpWidget(TestApp(dio: dio, cacheStore: cacheStore));
await tester.pumpAndSettle();
});
}
22 changes: 22 additions & 0 deletions flutter_map_cache/test/utils/functions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:dio/dio.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:http_mock_adapter/http_mock_adapter.dart';

Dio createDioReturningEmptyTiles() {
final dio = Dio();

final dioAdapter = DioAdapter(dio: dio);

const url = 'https://tile.openstreetmap.org/0/0/0.png';

dioAdapter.onGet(
url,
(server) => server.reply(
200,
TileProvider.transparentImage,
delay: const Duration(seconds: 1),
),
);

return dio;
}
38 changes: 38 additions & 0 deletions flutter_map_cache/test/utils/test_app.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import 'package:dio/dio.dart';
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_cache/flutter_map_cache.dart';
import 'package:latlong2/latlong.dart';

// ignore_for_file: diagnostic_describe_all_properties

class TestApp extends StatelessWidget {
final CacheStore cacheStore;
final Dio dio;

const TestApp({super.key, required this.cacheStore, required this.dio});

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: FlutterMap(
options: const MapOptions(
initialZoom: 0,
initialCenter: LatLng(0, 0),
),
children: [
TileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
tileProvider: CachedTileProvider(
store: cacheStore,
dio: dio,
),
),
],
),
),
);
}
}
Loading