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

feat: setup unit tests, improve test coverage #127

Merged
merged 36 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9266b13
try to split files
josxha Nov 3, 2024
024818d
fix import
josxha Nov 3, 2024
b89894f
another try
josxha Nov 3, 2024
3ee8c9d
Update ci.yml
josxha Nov 3, 2024
d4b9a97
try to use unit tests
josxha Nov 3, 2024
2e077b1
Update ci.yml
josxha Nov 3, 2024
9cee39e
Update ci.yml
josxha Nov 3, 2024
1027fd2
add general test group
josxha Nov 3, 2024
1cba70d
Update general_test.dart
josxha Nov 3, 2024
33d2b4e
Update controller_test.dart
josxha Nov 3, 2024
afff1a5
add tests
josxha Nov 3, 2024
bf82c33
Update codecov.yml
josxha Nov 3, 2024
31251fb
Update controller_test.dart
josxha Nov 3, 2024
64dfbc7
Update general_test.dart
josxha Nov 3, 2024
a3e4199
Update general_test.dart
josxha Nov 3, 2024
98f99f7
Update models_test.dart
josxha Nov 3, 2024
2dd6d1b
Update models_test.dart
josxha Nov 3, 2024
78fa383
Update models_test.dart
josxha Nov 3, 2024
789b4df
Update models_test.dart
josxha Nov 3, 2024
d74f46f
tests
josxha Nov 3, 2024
7a60ba2
add `MapOptions` getter and `MapOptions.of(context)`
josxha Nov 4, 2024
14cace5
dart format
josxha Nov 4, 2024
b3276cd
MapCamera tests
josxha Nov 4, 2024
1f75416
fix lint
josxha Nov 4, 2024
5fcfa06
try to fix integration tests for android 23
josxha Nov 4, 2024
0013a2a
Update main.dart
josxha Nov 4, 2024
afba221
enable some permission tests
josxha Nov 4, 2024
ec7b7ca
Update permission_manager_test.dart
josxha Nov 4, 2024
41cb5f7
Update permission_manager_test.dart
josxha Nov 4, 2024
061f0a4
Update permission_manager_test.dart
josxha Nov 4, 2024
905a943
Update permission_manager_test.dart
josxha Nov 4, 2024
4306889
Update models_test.dart
josxha Nov 4, 2024
04de242
add tests
josxha Nov 4, 2024
4da307a
fix tests
josxha Nov 4, 2024
239a3c8
disable download test
josxha Nov 4, 2024
5168bd1
Update main.dart
josxha Nov 4, 2024
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
28 changes: 24 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,29 @@ jobs:
# cache: true
# - run: flutter pub get
# - run: flutter test integration_test --no-pub -r expanded
unit-test-android:
name: "[Android] Unit tests"
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sdk: [ '3.24.3', '' ]
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: "Setup Flutter SDK"
uses: subosito/flutter-action@v2
with:
cache: true
- name: "Get Flutter dependencies"
run: flutter pub get
- name: "Run unit tests"
run: flutter test --timeout=600s --coverage
- name: "Run Codecov"
uses: codecov/codecov-action@v4
if: ${{ matrix.sdk == '' }}
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
integration-test-android:
name: "[Android] Integration tests"
runs-on: ubuntu-latest
Expand All @@ -71,9 +94,6 @@ jobs:
matrix:
api-level: [ 23, 34 ] # TODO: add 21
timeout-minutes: 30
defaults:
run:
working-directory: example
steps:
- uses: actions/checkout@v4
- name: "Setup Flutter SDK"
Expand All @@ -99,7 +119,7 @@ jobs:
api-level: ${{ matrix.api-level }}
arch: x86_64
emulator-boot-timeout: 1800 # 30 minutes
script: cd example && flutter test integration_test -r expanded --timeout=none --coverage --coverage-package maplibre
script: cd example && flutter test integration_test/main.dart --timeout=1800s -r expanded --coverage --coverage-package maplibre
- name: "Run Codecov"
uses: codecov/codecov-action@v4
if: ${{ matrix.api-level == '34' }}
Expand Down
9 changes: 9 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
comment:
# this posts no PR comment if there are no coverage changes
require_changes: true
status:
project:
default:
target: 0%
threshold: 0%

ignore:
- "**/*.g.dart"
- "lib/src/native/jni"
Expand Down
281 changes: 157 additions & 124 deletions example/integration_test/controller_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import 'dart:async';
import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:maplibre/maplibre.dart';
Expand All @@ -8,135 +11,165 @@ import 'app.dart';

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('controller', () {
testWidgets(
'render map',
(tester) async {
await tester.pumpWidget(const App());
await tester.pumpAndSettle();
expect(tester.allWidgets.any((w) => w is MapLibreMap), isTrue);
},
testWidgets('getCamera', (tester) async {
final ctrlCompleter = Completer<MapController>();
final app = App(
onMapCreated: ctrlCompleter.complete,
options: MapOptions(initCenter: Position(1, 2)),
);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
await ctrl.moveCamera(
center: Position(1, 1),
bearing: 1,
zoom: 1,
pitch: 1,
);
await tester.pumpAndSettle();
final camera = ctrl.getCamera();
expect(camera.center.lng, closeTo(1, 0.00001));
expect(camera.center.lat, closeTo(1, 0.00001));
expect(camera.zoom, closeTo(1, 0.00001));
expect(camera.bearing, closeTo(1, 0.00001));
expect(camera.pitch, closeTo(1, 0.00001));
});

testWidgets('toScreenLocation', (tester) async {
final ctrlCompleter = Completer<MapController>();
final app = App(
onMapCreated: ctrlCompleter.complete,
options: MapOptions(initCenter: Position(1, 2)),
);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
final offset = await ctrl.toScreenLocation(Position(1, 2));
// Different devices have different screen sizes.
expect(offset.dx, greaterThanOrEqualTo(0));
expect(offset.dy, greaterThanOrEqualTo(0));
});

testWidgets('moveCamera', (tester) async {
final ctrlCompleter = Completer<MapController>();
final app = App(onMapCreated: ctrlCompleter.complete);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
await ctrl.moveCamera(
center: Position(1, 2),
bearing: 1,
zoom: 1,
pitch: 1,
);
await tester.pumpAndSettle();
final camera = ctrl.getCamera();
expect(camera.center.lng, closeTo(1, 0.00001));
expect(camera.center.lat, closeTo(2, 0.00001));
expect(camera.zoom, closeTo(1, 0.00001));
expect(camera.bearing, closeTo(1, 0.00001));
expect(camera.pitch, closeTo(1, 0.00001));
});
});

testWidgets('add ImageSource', (tester) async {
final ctrlCompleter = Completer<MapController>();
final app = App(onMapCreated: ctrlCompleter.complete);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
final source = ImageSource(
id: '1',
url:
'https://raw.githubusercontent.com/josxha/flutter-maplibre/57396548693857a80083303f56aa83b4901dad48/docs/static/img/favicon-32x32.png',
coordinates: [Position(0, 0), Position(1, 1)],
);
testWidgets(
'getCamera',
(tester) async {
final ctrlCompleter = Completer<MapController>();
final app = App(
onMapCreated: ctrlCompleter.complete,
options: MapOptions(initCenter: Position(1, 2)),
);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
await ctrl.moveCamera(
center: Position(1, 1),
bearing: 1,
zoom: 1,
pitch: 1,
);
await tester.pumpAndSettle();
final camera = ctrl.getCamera();
expect(camera.center.lng, closeTo(1, 0.00001));
expect(camera.center.lat, closeTo(1, 0.00001));
expect(camera.zoom, closeTo(1, 0.00001));
expect(camera.bearing, closeTo(1, 0.00001));
expect(camera.pitch, closeTo(1, 0.00001));
},
await ctrl.addSource(source);
await tester.pumpAndSettle();
});

testWidgets('add GeoJsonSource', (tester) async {
final ctrlCompleter = Completer<MapController>();
final app = App(onMapCreated: ctrlCompleter.complete);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
final source = GeoJsonSource(
id: '1',
data: jsonEncode(
GeometryCollection(
geometries: [Point(coordinates: Position(12, 2))],
).toJson(),
),
);
await ctrl.addSource(source);
await tester.pumpAndSettle();
});

testWidgets('add VideoSource', (tester) async {
if (!kIsWeb) return; // VideoSource is only supported on web.
final ctrlCompleter = Completer<MapController>();
final app = App(onMapCreated: ctrlCompleter.complete);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
final source = VideoSource(
id: '1',
coordinates: [Position(0, 0), Position(10, 10)],
urls: [
'https://file-examples.com/storage/fefd65c2506728a13a07e72/2017/04/file_example_MP4_480_1_5MG.mp4',
],
);
testWidgets(
'moveCamera',
(tester) async {
final ctrlCompleter = Completer<MapController>();
final app = App(onMapCreated: ctrlCompleter.complete);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
await ctrl.moveCamera(
center: Position(1, 2),
bearing: 1,
zoom: 1,
pitch: 1,
);
await tester.pumpAndSettle();
final camera = ctrl.getCamera();
expect(camera.center.lng, closeTo(1, 0.00001));
expect(camera.center.lat, closeTo(2, 0.00001));
expect(camera.zoom, closeTo(1, 0.00001));
expect(camera.bearing, closeTo(1, 0.00001));
expect(camera.pitch, closeTo(1, 0.00001));
},
await ctrl.addSource(source);
await tester.pumpAndSettle();
});

testWidgets('add RasterDemSource', (tester) async {
final ctrlCompleter = Completer<MapController>();
final app = App(onMapCreated: ctrlCompleter.complete);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
const source = RasterDemSource(
id: '1',
url: 'https://demotiles.maplibre.org/terrain-tiles/tiles.json',
tileSize: 256,
);
/*testWidgets(
'animateCamera',
(tester) async {
final ctrlCompleter = Completer<MapController>();
final app = App(onMapCreated: ctrlCompleter.complete);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
await ctrl.animateCamera(
center: Position(2, 1),
bearing: 2,
zoom: 2,
pitch: 2,
webSpeed: 100,
nativeDuration: Duration.zero,
);
await tester.pumpAndSettle();
final camera = ctrl.getCamera();
expect(camera.center.lng, closeTo(2, 0.00001));
expect(camera.center.lat, closeTo(1, 0.00001));
expect(camera.zoom, closeTo(2, 0.00001));
expect(camera.bearing, closeTo(2, 0.00001));
expect(camera.pitch, closeTo(2, 0.00001));
},
);*/
/*testWidgets(
'animateCamera cancel',
(tester) async {
late final MapController ctrl;
final app = App(onMapCreated: (controller) => ctrl = controller);
await tester.pumpWidget(app);
await tester.pumpAndSettle();
final future = ctrl.flyTo(
center: Position(2, 2),
bearing: 2,
zoom: 2,
pitch: 2,
webSpeed: 0.1,
nativeDuration: const Duration(days: 1),
);
// TODO perform gesture
await expectLater(
future,
throwsA(isA<PlatformException>()),
);
},
await ctrl.addSource(source);
await tester.pumpAndSettle();
});

testWidgets('add RasterSource', (tester) async {
final ctrlCompleter = Completer<MapController>();
final app = App(onMapCreated: ctrlCompleter.complete);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
const source = RasterSource(
id: '1',
tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
maxZoom: 20,
tileSize: 256,
attribution:
'<a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
);
testWidgets(
'getMetersPerPixelAtLatitude',
(tester) async {
late final MapController ctrl;
final app = App(onMapCreated: (controller) => ctrl = controller);
await tester.pumpWidget(app);
await tester.pumpAndSettle();
final meters = await ctrl.getMetersPerPixelAtLatitude(23);
// TODO adjust value
expect(meters, closeTo(12345, 0.00001));
},
await ctrl.addSource(source);
await tester.pumpAndSettle();
});

testWidgets('add VectorSource', (tester) async {
final ctrlCompleter = Completer<MapController>();
final app = App(onMapCreated: ctrlCompleter.complete);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
const source = VectorSource(
id: '1',
url: 'https://demotiles.maplibre.org/tiles/tiles.json',
);
testWidgets(
'getVisibleRegion',
(tester) async {
late final MapController ctrl;
final app = App(onMapCreated: (controller) => ctrl = controller);
await tester.pumpWidget(app);
await tester.pumpAndSettle();
final region = await ctrl.getVisibleRegion();
// TODO adjust values
expect(region.latitudeNorth, closeTo(85.05112862791722, 0.00001));
expect(region.latitudeSouth, closeTo(12345, 0.00001));
expect(region.longitudeEast, closeTo(12345, 0.00001));
expect(region.longitudeWest, closeTo(12345, 0.00001));
},
);*/
await ctrl.addSource(source);
await tester.pumpAndSettle();
});

testWidgets('add BackgroundLayer', (tester) async {
final ctrlCompleter = Completer<MapController>();
final app = App(onMapCreated: ctrlCompleter.complete);
await tester.pumpWidget(app);
final ctrl = await ctrlCompleter.future;
const layer = BackgroundLayer(id: '1', color: Colors.black);
await ctrl.addLayer(layer);
await tester.pumpAndSettle();
});
}
Loading