mirror of
https://github.com/flutter/samples.git
synced 2026-04-02 17:52:56 +00:00
Compass app (#2446)
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:compass_app/data/repositories/activity/activity_repository_local.dart';
|
||||
import 'package:compass_app/data/services/local/local_data_service.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('ActivityRepositoryLocal tests', () {
|
||||
// To load assets
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
final repository = ActivityRepositoryLocal(
|
||||
localDataService: LocalDataService(),
|
||||
);
|
||||
|
||||
test('should get by destination ref', () async {
|
||||
final result = await repository.getByDestination('alaska');
|
||||
expect(result, isA<Ok>());
|
||||
|
||||
final list = result.asOk.value;
|
||||
expect(list.length, 20);
|
||||
|
||||
final activity = list.first;
|
||||
expect(activity.name, 'Glacier Trekking and Ice Climbing');
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:compass_app/data/repositories/activity/activity_repository.dart';
|
||||
import 'package:compass_app/data/repositories/activity/activity_repository_remote.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../../testing/fakes/services/fake_api_client.dart';
|
||||
|
||||
void main() {
|
||||
group('ActivityRepositoryRemote tests', () {
|
||||
late FakeApiClient apiClient;
|
||||
late ActivityRepository repository;
|
||||
|
||||
setUp(() {
|
||||
apiClient = FakeApiClient();
|
||||
repository = ActivityRepositoryRemote(apiClient: apiClient);
|
||||
});
|
||||
|
||||
test('should get activities for destination', () async {
|
||||
final result = await repository.getByDestination('alaska');
|
||||
expect(result, isA<Ok>());
|
||||
|
||||
final list = result.asOk.value;
|
||||
expect(list.length, 1);
|
||||
|
||||
final destination = list.first;
|
||||
expect(destination.name, 'Glacier Trekking and Ice Climbing');
|
||||
|
||||
// Only one request happened
|
||||
expect(apiClient.requestCount, 1);
|
||||
});
|
||||
|
||||
test('should get destinations from cache', () async {
|
||||
// Request destination once
|
||||
var result = await repository.getByDestination('alaska');
|
||||
expect(result, isA<Ok>());
|
||||
|
||||
// Request destination another time
|
||||
result = await repository.getByDestination('alaska');
|
||||
expect(result, isA<Ok>());
|
||||
|
||||
// Only one request happened
|
||||
expect(apiClient.requestCount, 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:compass_app/data/repositories/auth/auth_repository_remote.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../../testing/fakes/services/fake_api_client.dart';
|
||||
import '../../../../testing/fakes/services/fake_auth_api_client.dart';
|
||||
import '../../../../testing/fakes/services/fake_shared_preferences_service.dart';
|
||||
|
||||
void main() {
|
||||
group('AuthRepositoryRemote tests', () {
|
||||
late FakeApiClient apiClient;
|
||||
late FakeAuthApiClient authApiClient;
|
||||
late FakeSharedPreferencesService sharedPreferencesService;
|
||||
late AuthRepositoryRemote repository;
|
||||
|
||||
setUp(() {
|
||||
apiClient = FakeApiClient();
|
||||
authApiClient = FakeAuthApiClient();
|
||||
sharedPreferencesService = FakeSharedPreferencesService();
|
||||
repository = AuthRepositoryRemote(
|
||||
apiClient: apiClient,
|
||||
authApiClient: authApiClient,
|
||||
sharedPreferencesService: sharedPreferencesService,
|
||||
);
|
||||
});
|
||||
|
||||
test('fetch on start, has token', () async {
|
||||
// Stored token in shared preferences
|
||||
sharedPreferencesService.token = 'TOKEN';
|
||||
|
||||
// Create an AuthRepository, should perform initial fetch
|
||||
final repository = AuthRepositoryRemote(
|
||||
apiClient: apiClient,
|
||||
authApiClient: authApiClient,
|
||||
sharedPreferencesService: sharedPreferencesService,
|
||||
);
|
||||
|
||||
final isAuthenticated = await repository.isAuthenticated;
|
||||
|
||||
// True because Token is SharedPreferences
|
||||
expect(isAuthenticated, isTrue);
|
||||
|
||||
// Check auth token
|
||||
await expectAuthHeader(apiClient, 'Bearer TOKEN');
|
||||
});
|
||||
|
||||
test('fetch on start, no token', () async {
|
||||
// Stored token in shared preferences
|
||||
sharedPreferencesService.token = null;
|
||||
|
||||
// Create an AuthRepository, should perform initial fetch
|
||||
final repository = AuthRepositoryRemote(
|
||||
apiClient: apiClient,
|
||||
authApiClient: authApiClient,
|
||||
sharedPreferencesService: sharedPreferencesService,
|
||||
);
|
||||
|
||||
final isAuthenticated = await repository.isAuthenticated;
|
||||
|
||||
// True because Token is SharedPreferences
|
||||
expect(isAuthenticated, isFalse);
|
||||
|
||||
// Check auth token
|
||||
await expectAuthHeader(apiClient, null);
|
||||
});
|
||||
|
||||
test('perform login', () async {
|
||||
final result = await repository.login(
|
||||
email: 'EMAIL',
|
||||
password: 'PASSWORD',
|
||||
);
|
||||
expect(result, isA<Ok>());
|
||||
expect(await repository.isAuthenticated, isTrue);
|
||||
expect(sharedPreferencesService.token, 'TOKEN');
|
||||
|
||||
// Check auth token
|
||||
await expectAuthHeader(apiClient, 'Bearer TOKEN');
|
||||
});
|
||||
|
||||
test('perform logout', () async {
|
||||
// logged in status
|
||||
sharedPreferencesService.token = 'TOKEN';
|
||||
|
||||
final result = await repository.logout();
|
||||
expect(result, isA<Ok>());
|
||||
expect(await repository.isAuthenticated, isFalse);
|
||||
expect(sharedPreferencesService.token, null);
|
||||
|
||||
// Check auth token
|
||||
await expectAuthHeader(apiClient, null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> expectAuthHeader(FakeApiClient apiClient, String? header) async {
|
||||
final header = apiClient.authHeaderProvider?.call();
|
||||
expect(header, header);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:compass_app/data/repositories/booking/booking_repository.dart';
|
||||
import 'package:compass_app/data/repositories/booking/booking_repository_remote.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../../testing/fakes/services/fake_api_client.dart';
|
||||
import '../../../../testing/models/booking.dart';
|
||||
|
||||
void main() {
|
||||
group('BookingRepositoryRemote tests', () {
|
||||
late BookingRepository bookingRepository;
|
||||
late FakeApiClient fakeApiClient;
|
||||
|
||||
setUp(() {
|
||||
fakeApiClient = FakeApiClient();
|
||||
bookingRepository = BookingRepositoryRemote(
|
||||
apiClient: fakeApiClient,
|
||||
);
|
||||
});
|
||||
|
||||
test('should get booking', () async {
|
||||
final result = await bookingRepository.getBooking(0);
|
||||
final booking = result.asOk.value;
|
||||
expect(booking, kBooking.copyWith(id: 0));
|
||||
});
|
||||
|
||||
test('should create booking', () async {
|
||||
expect(fakeApiClient.bookings, isEmpty);
|
||||
final result = await bookingRepository.createBooking(kBooking);
|
||||
expect(result, isA<Ok<void>>());
|
||||
expect(fakeApiClient.bookings.first, kBookingApiModel);
|
||||
});
|
||||
|
||||
test('should get list of booking', () async {
|
||||
final result = await bookingRepository.getBookingsList();
|
||||
final list = result.asOk.value;
|
||||
expect(list, [kBookingSummary]);
|
||||
});
|
||||
|
||||
test('should delete booking', () async {
|
||||
// Ensure no bookings exist
|
||||
expect(fakeApiClient.bookings, isEmpty);
|
||||
|
||||
// Add a booking
|
||||
var result = await bookingRepository.createBooking(kBooking);
|
||||
expect(result, isA<Ok<void>>());
|
||||
|
||||
// Delete the booking
|
||||
result = await bookingRepository.delete(0);
|
||||
expect(result, isA<Ok<void>>());
|
||||
|
||||
// Check if the booking was deleted from the server
|
||||
expect(fakeApiClient.bookings, isEmpty);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:compass_app/data/repositories/continent/continent_repository.dart';
|
||||
import 'package:compass_app/data/repositories/continent/continent_repository_remote.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../../testing/fakes/services/fake_api_client.dart';
|
||||
|
||||
void main() {
|
||||
group('ContinentRepositoryRemote tests', () {
|
||||
late FakeApiClient apiClient;
|
||||
late ContinentRepository repository;
|
||||
|
||||
setUp(() {
|
||||
apiClient = FakeApiClient();
|
||||
repository = ContinentRepositoryRemote(apiClient: apiClient);
|
||||
});
|
||||
|
||||
test('should get continents', () async {
|
||||
final result = await repository.getContinents();
|
||||
expect(result, isA<Ok>());
|
||||
|
||||
final list = result.asOk.value;
|
||||
expect(list.length, 3);
|
||||
|
||||
final destination = list.first;
|
||||
expect(destination.name, 'CONTINENT');
|
||||
|
||||
// Only one request happened
|
||||
expect(apiClient.requestCount, 1);
|
||||
});
|
||||
|
||||
test('should get continents from cache', () async {
|
||||
// Request continents once
|
||||
var result = await repository.getContinents();
|
||||
expect(result, isA<Ok>());
|
||||
|
||||
// Request continents another time
|
||||
result = await repository.getContinents();
|
||||
expect(result, isA<Ok>());
|
||||
|
||||
// Only one request happened
|
||||
expect(apiClient.requestCount, 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:compass_app/data/services/local/local_data_service.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
import 'package:compass_app/data/repositories/destination/destination_repository_local.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('DestinationRepositoryLocal tests', () {
|
||||
// To load assets
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
final repository = DestinationRepositoryLocal(
|
||||
localDataService: LocalDataService(),
|
||||
);
|
||||
|
||||
test('should load and parse', () async {
|
||||
// Should load the json and parse it
|
||||
final result = await repository.getDestinations();
|
||||
expect(result, isA<Ok>());
|
||||
|
||||
// Check that the list is complete
|
||||
final list = result.asOk.value;
|
||||
expect(list.length, 137);
|
||||
|
||||
// Check first item
|
||||
final destination = list.first;
|
||||
expect(destination.name, 'Alaska');
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:compass_app/data/repositories/destination/destination_repository.dart';
|
||||
import 'package:compass_app/data/repositories/destination/destination_repository_remote.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../../testing/fakes/services/fake_api_client.dart';
|
||||
|
||||
void main() {
|
||||
group('DestinationRepositoryRemote tests', () {
|
||||
late FakeApiClient apiClient;
|
||||
late DestinationRepository repository;
|
||||
|
||||
setUp(() {
|
||||
apiClient = FakeApiClient();
|
||||
repository = DestinationRepositoryRemote(apiClient: apiClient);
|
||||
});
|
||||
|
||||
test('should get destinations', () async {
|
||||
final result = await repository.getDestinations();
|
||||
expect(result, isA<Ok>());
|
||||
|
||||
final list = result.asOk.value;
|
||||
expect(list.length, 2);
|
||||
|
||||
final destination = list.first;
|
||||
expect(destination.name, 'name1');
|
||||
|
||||
// Only one request happened
|
||||
expect(apiClient.requestCount, 1);
|
||||
});
|
||||
|
||||
test('should get destinations from cache', () async {
|
||||
// Request destination once
|
||||
var result = await repository.getDestinations();
|
||||
expect(result, isA<Ok>());
|
||||
|
||||
// Request destination another time
|
||||
result = await repository.getDestinations();
|
||||
expect(result, isA<Ok>());
|
||||
|
||||
// Only one request happened
|
||||
expect(apiClient.requestCount, 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
83
compass_app/app/test/data/services/api/api_client_test.dart
Normal file
83
compass_app/app/test/data/services/api/api_client_test.dart
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:compass_app/data/services/api/api_client.dart';
|
||||
import 'package:compass_app/domain/models/continent/continent.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../../testing/mocks.dart';
|
||||
import '../../../../testing/models/activity.dart';
|
||||
import '../../../../testing/models/booking.dart';
|
||||
import '../../../../testing/models/destination.dart';
|
||||
import '../../../../testing/models/user.dart';
|
||||
|
||||
void main() {
|
||||
group('ApiClient', () {
|
||||
late MockHttpClient mockHttpClient;
|
||||
late ApiClient apiClient;
|
||||
|
||||
setUp(() {
|
||||
mockHttpClient = MockHttpClient();
|
||||
apiClient = ApiClient(clientFactory: () => mockHttpClient);
|
||||
});
|
||||
|
||||
test('should get continents', () async {
|
||||
final continents = [const Continent(name: 'NAME', imageUrl: 'URL')];
|
||||
mockHttpClient.mockGet('/continent', continents);
|
||||
final result = await apiClient.getContinents();
|
||||
expect(result.asOk.value, continents);
|
||||
});
|
||||
|
||||
test('should get activities by destination', () async {
|
||||
final activites = [kActivity];
|
||||
mockHttpClient.mockGet(
|
||||
'/destination/${kDestination1.ref}/activity',
|
||||
activites,
|
||||
);
|
||||
final result =
|
||||
await apiClient.getActivityByDestination(kDestination1.ref);
|
||||
expect(result.asOk.value, activites);
|
||||
});
|
||||
|
||||
test('should get booking', () async {
|
||||
mockHttpClient.mockGet(
|
||||
'/booking/${kBookingApiModel.id}',
|
||||
kBookingApiModel,
|
||||
);
|
||||
final result = await apiClient.getBooking(kBookingApiModel.id!);
|
||||
expect(result.asOk.value, kBookingApiModel);
|
||||
});
|
||||
|
||||
test('should get bookings', () async {
|
||||
mockHttpClient.mockGet('/booking', [kBookingApiModel]);
|
||||
final result = await apiClient.getBookings();
|
||||
expect(result.asOk.value, [kBookingApiModel]);
|
||||
});
|
||||
|
||||
test('should get destinations', () async {
|
||||
mockHttpClient.mockGet('/destination', [kDestination1]);
|
||||
final result = await apiClient.getDestinations();
|
||||
expect(result.asOk.value, [kDestination1]);
|
||||
});
|
||||
|
||||
test('should get user', () async {
|
||||
mockHttpClient.mockGet('/user', userApiModel);
|
||||
final result = await apiClient.getUser();
|
||||
expect(result.asOk.value, userApiModel);
|
||||
});
|
||||
|
||||
test('should post booking', () async {
|
||||
mockHttpClient.mockPost('/booking', kBookingApiModel);
|
||||
final result = await apiClient.postBooking(kBookingApiModel);
|
||||
expect(result.asOk.value, kBookingApiModel);
|
||||
});
|
||||
|
||||
test('should delete booking', () async {
|
||||
mockHttpClient.mockDelete('/booking/0');
|
||||
final result = await apiClient.deleteBooking(0);
|
||||
expect(result, isA<Ok<void>>());
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:compass_app/data/services/api/auth_api_client.dart';
|
||||
import 'package:compass_app/data/services/api/model/login_request/login_request.dart';
|
||||
import 'package:compass_app/data/services/api/model/login_response/login_response.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../../testing/mocks.dart';
|
||||
|
||||
void main() {
|
||||
group('AuthApiClient', () {
|
||||
late MockHttpClient mockHttpClient;
|
||||
late AuthApiClient apiClient;
|
||||
|
||||
setUp(() {
|
||||
mockHttpClient = MockHttpClient();
|
||||
apiClient = AuthApiClient(clientFactory: () => mockHttpClient);
|
||||
});
|
||||
|
||||
test('should post login', () async {
|
||||
const loginResponse = LoginResponse(
|
||||
token: 'TOKEN',
|
||||
userId: '123',
|
||||
);
|
||||
mockHttpClient.mockPost(
|
||||
'/login',
|
||||
loginResponse,
|
||||
200,
|
||||
);
|
||||
final result = await apiClient.login(
|
||||
const LoginRequest(
|
||||
email: 'EMAIL',
|
||||
password: 'PASSWORD',
|
||||
),
|
||||
);
|
||||
expect(result.asOk.value, loginResponse);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user