Skip to content

Commit

Permalink
Migrate web tests to support sound null safety (#1380)
Browse files Browse the repository at this point in the history
* Migrate geolocator web tests to support sound null safety

* Update version information and change log

* Add generated mock files

* Fix mock files

---------

Co-authored-by: Maurits van Beusekom <[email protected]>
  • Loading branch information
ChristianEdwardPadilla and mvanbeusekom authored Jan 31, 2024
1 parent 18a0b21 commit d4b5304
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 122 deletions.
4 changes: 4 additions & 0 deletions geolocator_web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.2.1

- Migrate tests to support sound null safety.

## 2.2.0

- Exposes altitude accuracy field in `Position` object.
Expand Down
5 changes: 3 additions & 2 deletions geolocator_web/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: geolocator_web
description: Official web implementation of the geolocator plugin.
repository: https://github.com/baseflow/flutter-geolocator/tree/main/geolocator_web
issue_tracker: https://github.com/baseflow/flutter-geolocator/issues?q=is%3Aissue+is%3Aopen
version: 2.2.0
version: 2.2.1

flutter:
plugin:
Expand All @@ -23,7 +23,8 @@ dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.1
mockito: ^5.0.0
mockito: ^5.4.0


environment:
sdk: '>=2.15.0 <4.0.0'
Expand Down
16 changes: 10 additions & 6 deletions geolocator_web/test/geolocator_utils_test.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import 'dart:html' as html;
import 'dart:async';
import 'dart:html';

import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:geolocator_platform_interface/geolocator_platform_interface.dart';
import 'package:geolocator_web/src/utils.dart';
import 'package:mockito/mockito.dart';

import 'geolocator_utils_test.mocks.dart';

@GenerateNiceMocks([
MockSpec<Geoposition>(),
MockSpec<PositionError>(),
])
void main() {
test('toPosition should throw a exception if coords is null', () {
final geoposition = MockGeoposition();
Expand Down Expand Up @@ -39,7 +47,3 @@ void main() {
expect(convertPositionError(positionError), isA<PlatformException>());
});
}

class MockGeoposition extends Mock implements html.Geoposition {}

class MockPositionError extends Mock implements html.PositionError {}
31 changes: 31 additions & 0 deletions geolocator_web/test/geolocator_utils_test.mocks.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Mocks generated by Mockito 5.4.1-wip from annotations
// in geolocator.web/test/geolocator_utils_test.dart.
// Do not manually edit this file.

// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:html' as _i2;

import 'package:mockito/mockito.dart' as _i1;

// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
// ignore_for_file: avoid_setters_without_getters
// ignore_for_file: comment_references
// ignore_for_file: deprecated_member_use
// ignore_for_file: deprecated_member_use_from_same_package
// ignore_for_file: implementation_imports
// ignore_for_file: invalid_use_of_visible_for_testing_member
// ignore_for_file: prefer_const_constructors
// ignore_for_file: unnecessary_parenthesis
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class

/// A class which mocks [Geoposition].
///
/// See the documentation for Mockito's code generation for more information.
class MockGeoposition extends _i1.Mock implements _i2.Geoposition {}

/// A class which mocks [PositionError].
///
/// See the documentation for Mockito's code generation for more information.
class MockPositionError extends _i1.Mock implements _i2.PositionError {}
144 changes: 30 additions & 114 deletions geolocator_web/test/geolocator_web_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:geolocator_web/geolocator_web.dart';
import 'package:geolocator_web/src/geolocation_manager.dart';
import 'package:geolocator_web/src/permissions_manager.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';

import 'geolocator_web_test.mocks.dart';

List<Position> get mockPositions => List.of(() sync* {
for (var i = 0; i < 5; i++) {
yield Position(
Expand All @@ -24,86 +27,49 @@ List<Position> get mockPositions => List.of(() sync* {
}
}());

@GenerateNiceMocks([
MockSpec<GeolocationManager>(),
MockSpec<PermissionsManager>(),
])
void main() {
test(
'enableHighAccuracy returns the correct value depending on given accuracy in getPositionStream method',
() async {
final mockGeolocationManager = MockGeolocationManager();
final mockPermissionManager = MockPermissionManager();
final geolocatorPlugin =
GeolocatorPlugin.private(mockGeolocationManager, mockPermissionManager);

geolocatorPlugin.getPositionStream(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.medium,
),
);
expect(mockGeolocationManager.enableHighAccuracy, false);

geolocatorPlugin.getPositionStream(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.best,
),
);
expect(mockGeolocationManager.enableHighAccuracy, true);
});

test(
'enableHighAccuracy returns the correct value depending on given accuracy in getCurrentPosition method',
() async {
final mockGeolocationManager = MockGeolocationManager();
final mockPermissionManager = MockPermissionManager();
final geolocatorPlugin =
GeolocatorPlugin.private(mockGeolocationManager, mockPermissionManager);

geolocatorPlugin.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.medium,
),
);
expect(mockGeolocationManager.enableHighAccuracy, false);

geolocatorPlugin.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
),
);
expect(mockGeolocationManager.enableHighAccuracy, true);
late MockGeolocationManager mockGeolocationManager;
late MockPermissionsManager mockPermissionsManager;
late GeolocatorPlugin geolocatorPlugin;

setUp(() {
mockGeolocationManager = MockGeolocationManager();
mockPermissionsManager = MockPermissionsManager();
geolocatorPlugin = GeolocatorPlugin.private(
mockGeolocationManager, mockPermissionsManager);

when(mockGeolocationManager.getCurrentPosition(
enableHighAccuracy: anyNamed('enableHighAccuracy'),
timeout: anyNamed('timeout')))
.thenAnswer((_) async => mockPositions.first);
when(mockGeolocationManager.watchPosition(
enableHighAccuracy: anyNamed('enableHighAccuracy'),
timeout: anyNamed('timeout')))
.thenAnswer((_) => Stream.fromIterable(mockPositions));
});

group('Permission methods', () {
test('checkPermission throws exception when permissionsSupported is false',
() {
final mockGeolocationManager = MockGeolocationManager();
final mockPermissionManager = MockPermissionManager();
final geolocatorPlugin = GeolocatorPlugin.private(
mockGeolocationManager, mockPermissionManager);

when(mockPermissionManager.permissionsSupported).thenReturn(false);
() async {
when(mockPermissionsManager.permissionsSupported).thenReturn(false);

expect(
geolocatorPlugin.checkPermission, throwsA(isA<PlatformException>()));
});

test('checkPermission returns the correct LocationPermission', () async {
final mockGeolocationManager = MockGeolocationManager();
final mockPermissionManager = MockPermissionManager();
final geolocatorPlugin = GeolocatorPlugin.private(
mockGeolocationManager, mockPermissionManager);

when(mockPermissionManager.permissionsSupported).thenReturn(true);
when(mockPermissionsManager.permissionsSupported).thenReturn(true);

await geolocatorPlugin.checkPermission();

verify(mockPermissionManager.query({'name': 'geolocation'})).called(1);
verify(mockPermissionsManager.query({'name': 'geolocation'})).called(1);
});

test('requestPermission returns LocationPermission.whileInUse', () async {
final mockGeolocationManager = MockGeolocationManager();
final mockPermissionManager = MockPermissionManager();
final geolocatorPlugin = GeolocatorPlugin.private(
mockGeolocationManager, mockPermissionManager);

final result = await geolocatorPlugin.requestPermission();

expect(result, LocationPermission.whileInUse);
Expand All @@ -112,11 +78,6 @@ void main() {

group('getCurrentPosition method', () {
test('getCurrentPosition should return a valid position', () async {
final mockGeolocationManager = MockGeolocationManager();
final mockPermissionManager = MockPermissionManager();
final geolocatorPlugin = GeolocatorPlugin.private(
mockGeolocationManager, mockPermissionManager);

final position = await geolocatorPlugin.getCurrentPosition(
locationSettings: const LocationSettings());
expect(position, mockPositions.first);
Expand All @@ -125,24 +86,14 @@ void main() {

group('getPositionStream method', () {
test('getPositionStream should return all mocked positions', () {
final mockGeolocationManager = MockGeolocationManager();
final mockPermissionManager = MockPermissionManager();
final geolocatorPlugin = GeolocatorPlugin.private(
mockGeolocationManager, mockPermissionManager);

final positionsStream = geolocatorPlugin.getPositionStream(
locationSettings: const LocationSettings());

expect(positionsStream, emitsInOrder(mockPositions));
});

test('getPositionStream should filter out mocked positions', () {
final mockGeolocationManager = MockGeolocationManager();
final mockPermissionManager = MockPermissionManager();
final geolocatorPlugin = GeolocatorPlugin.private(
mockGeolocationManager, mockPermissionManager);

var mockPositionsForFilter = List.of(() sync* {
final mockPositionsForFilter = List.of(() sync* {
for (var i = 0; i < 3; i++) {
yield Position(
latitude: 52.2669748 + i * 0.00005,
Expand Down Expand Up @@ -173,53 +124,18 @@ void main() {

group('Unsupported exceptions', () {
test('getLastKnownPosition throws unsupported exception', () async {
final mockGeolocationManager = MockGeolocationManager();
final mockPermissionManager = MockPermissionManager();
final geolocatorPlugin = GeolocatorPlugin.private(
mockGeolocationManager, mockPermissionManager);

expect(geolocatorPlugin.getLastKnownPosition,
throwsA(isA<PlatformException>()));
});

test('openAppSettings throws unsupported exception', () async {
final mockGeolocationManager = MockGeolocationManager();
final mockPermissionManager = MockPermissionManager();
final geolocatorPlugin = GeolocatorPlugin.private(
mockGeolocationManager, mockPermissionManager);

expect(
geolocatorPlugin.openAppSettings, throwsA(isA<PlatformException>()));
});

test('openLocationSettings throws unsupported exception', () async {
final mockGeolocationManager = MockGeolocationManager();
final mockPermissionManager = MockPermissionManager();
final geolocatorPlugin = GeolocatorPlugin.private(
mockGeolocationManager, mockPermissionManager);

expect(geolocatorPlugin.openLocationSettings,
throwsA(isA<PlatformException>()));
});
});
}

class MockGeolocationManager implements GeolocationManager {
bool? enableHighAccuracy;

@override
Future<Position> getCurrentPosition(
{bool? enableHighAccuracy, Duration? timeout}) {
this.enableHighAccuracy = enableHighAccuracy;
return Future.value(mockPositions.first);
}

@override
Stream<Position> watchPosition(
{bool? enableHighAccuracy, Duration? timeout}) {
this.enableHighAccuracy = enableHighAccuracy;
return Stream.fromIterable(mockPositions);
}
}

class MockPermissionManager extends Mock implements PermissionsManager {}
Loading

0 comments on commit d4b5304

Please sign in to comment.