snapshot of https://github.com/flutter/samples.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Main Branch CI / Test Flutter beta on ubuntu-latest (push) Has been skipped
Main Branch CI / Test Flutter stable on ubuntu-latest (push) Has been skipped
Main Branch CI / Test Flutter beta on macos-latest (push) Has been cancelled
Main Branch CI / Test Flutter stable on macos-latest (push) Has been cancelled
Some checks failed
Main Branch CI / Test Flutter beta on ubuntu-latest (push) Has been skipped
Main Branch CI / Test Flutter stable on ubuntu-latest (push) Has been skipped
Main Branch CI / Test Flutter beta on macos-latest (push) Has been cancelled
Main Branch CI / Test Flutter stable on macos-latest (push) Has been cancelled
This commit is contained in:
38
compass_app/app/testing/app.dart
Normal file
38
compass_app/app/testing/app.dart
Normal file
@@ -0,0 +1,38 @@
|
||||
// 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/ui/core/localization/applocalization.dart';
|
||||
import 'package:compass_app/ui/core/themes/theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mocktail_image_network/mocktail_image_network.dart';
|
||||
|
||||
import 'mocks.dart';
|
||||
|
||||
Future<void> testApp(
|
||||
WidgetTester tester,
|
||||
Widget body, {
|
||||
GoRouter? goRouter,
|
||||
}) async {
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
await tester.binding.setSurfaceSize(const Size(1200, 800));
|
||||
await mockNetworkImages(() async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
localizationsDelegates: [
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
AppLocalizationDelegate(),
|
||||
],
|
||||
theme: AppTheme.lightTheme,
|
||||
home: InheritedGoRouter(
|
||||
goRouter: goRouter ?? MockGoRouter(),
|
||||
child: Scaffold(body: body),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// 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/domain/models/activity/activity.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../../models/activity.dart';
|
||||
import '../../models/destination.dart';
|
||||
|
||||
class FakeActivityRepository implements ActivityRepository {
|
||||
Map<String, List<Activity>> activities = {
|
||||
"DESTINATION": [kActivity],
|
||||
kDestination1.ref: [kActivity],
|
||||
};
|
||||
|
||||
@override
|
||||
Future<Result<List<Activity>>> getByDestination(String ref) {
|
||||
return SynchronousFuture(Result.ok(activities[ref]!));
|
||||
}
|
||||
}
|
||||
@@ -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/auth/auth_repository.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
|
||||
class FakeAuthRepository extends AuthRepository {
|
||||
String? token;
|
||||
|
||||
@override
|
||||
Future<bool> get isAuthenticated async => token != null;
|
||||
|
||||
@override
|
||||
Future<Result<void>> login({
|
||||
required String email,
|
||||
required String password,
|
||||
}) async {
|
||||
token = 'TOKEN';
|
||||
notifyListeners();
|
||||
return Result.ok(null);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> logout() async {
|
||||
token = null;
|
||||
notifyListeners();
|
||||
return Result.ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// 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/domain/models/booking/booking.dart';
|
||||
import 'package:compass_app/domain/models/booking/booking_summary.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
|
||||
class FakeBookingRepository implements BookingRepository {
|
||||
List<Booking> bookings = List.empty(growable: true);
|
||||
int sequentialId = 0;
|
||||
|
||||
@override
|
||||
Future<Result<void>> createBooking(Booking booking) async {
|
||||
final bookingWithId = booking.copyWith(id: sequentialId++);
|
||||
bookings.add(bookingWithId);
|
||||
return Result.ok(null);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Booking>> getBooking(int id) async {
|
||||
return Result.ok(bookings[id]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<BookingSummary>>> getBookingsList() async {
|
||||
return Result.ok(_createSummaries());
|
||||
}
|
||||
|
||||
List<BookingSummary> _createSummaries() {
|
||||
return bookings
|
||||
.map(
|
||||
(booking) => BookingSummary(
|
||||
id: booking.id!,
|
||||
name:
|
||||
'${booking.destination.name}, ${booking.destination.continent}',
|
||||
startDate: booking.startDate,
|
||||
endDate: booking.endDate,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> delete(int id) async {
|
||||
bookings.removeWhere((booking) => booking.id == id);
|
||||
return Result.ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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/domain/models/continent/continent.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class FakeContinentRepository implements ContinentRepository {
|
||||
@override
|
||||
Future<Result<List<Continent>>> getContinents() {
|
||||
return SynchronousFuture(
|
||||
Result.ok([
|
||||
const Continent(name: 'CONTINENT', imageUrl: 'URL'),
|
||||
const Continent(name: 'CONTINENT2', imageUrl: 'URL'),
|
||||
const Continent(name: 'CONTINENT3', imageUrl: 'URL'),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// 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/domain/models/destination/destination.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../../models/destination.dart';
|
||||
|
||||
class FakeDestinationRepository implements DestinationRepository {
|
||||
@override
|
||||
Future<Result<List<Destination>>> getDestinations() {
|
||||
return SynchronousFuture(Result.ok([kDestination1, kDestination2]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// 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/itinerary_config/itinerary_config_repository.dart';
|
||||
import 'package:compass_app/domain/models/itinerary_config/itinerary_config.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class FakeItineraryConfigRepository implements ItineraryConfigRepository {
|
||||
FakeItineraryConfigRepository({this.itineraryConfig});
|
||||
|
||||
ItineraryConfig? itineraryConfig;
|
||||
|
||||
@override
|
||||
Future<Result<ItineraryConfig>> getItineraryConfig() {
|
||||
return SynchronousFuture(
|
||||
Result.ok(itineraryConfig ?? const ItineraryConfig()),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> setItineraryConfig(ItineraryConfig itineraryConfig) {
|
||||
this.itineraryConfig = itineraryConfig;
|
||||
return SynchronousFuture(Result.ok(null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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/user/user_repository.dart';
|
||||
import 'package:compass_app/domain/models/user/user.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
|
||||
import '../../models/user.dart';
|
||||
|
||||
class FakeUserRepository implements UserRepository {
|
||||
@override
|
||||
Future<Result<User>> getUser() async {
|
||||
return Result.ok(user);
|
||||
}
|
||||
}
|
||||
118
compass_app/app/testing/fakes/services/fake_api_client.dart
Normal file
118
compass_app/app/testing/fakes/services/fake_api_client.dart
Normal file
@@ -0,0 +1,118 @@
|
||||
// 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/data/services/api/model/booking/booking_api_model.dart';
|
||||
import 'package:compass_app/data/services/api/model/user/user_api_model.dart';
|
||||
import 'package:compass_app/domain/models/activity/activity.dart';
|
||||
import 'package:compass_app/domain/models/continent/continent.dart';
|
||||
import 'package:compass_app/domain/models/destination/destination.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
|
||||
import '../../models/activity.dart';
|
||||
import '../../models/booking.dart';
|
||||
import '../../models/user.dart';
|
||||
|
||||
class FakeApiClient implements ApiClient {
|
||||
// Should not increase when using cached data
|
||||
int requestCount = 0;
|
||||
|
||||
@override
|
||||
Future<Result<List<Continent>>> getContinents() async {
|
||||
requestCount++;
|
||||
return Result.ok([
|
||||
const Continent(name: 'CONTINENT', imageUrl: 'URL'),
|
||||
const Continent(name: 'CONTINENT2', imageUrl: 'URL'),
|
||||
const Continent(name: 'CONTINENT3', imageUrl: 'URL'),
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<Destination>>> getDestinations() async {
|
||||
requestCount++;
|
||||
return Result.ok([
|
||||
const Destination(
|
||||
ref: 'ref1',
|
||||
name: 'name1',
|
||||
country: 'country1',
|
||||
continent: 'Europe',
|
||||
knownFor: 'knownFor1',
|
||||
tags: ['tags1'],
|
||||
imageUrl: 'imageUrl1',
|
||||
),
|
||||
const Destination(
|
||||
ref: 'ref2',
|
||||
name: 'name2',
|
||||
country: 'country2',
|
||||
continent: 'Europe',
|
||||
knownFor: 'knownFor2',
|
||||
tags: ['tags2'],
|
||||
imageUrl: 'imageUrl2',
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<Activity>>> getActivityByDestination(String ref) async {
|
||||
requestCount++;
|
||||
|
||||
if (ref == 'alaska') {
|
||||
return Result.ok([
|
||||
const Activity(
|
||||
name: 'Glacier Trekking and Ice Climbing',
|
||||
description:
|
||||
'Embark on a thrilling adventure exploring the awe-inspiring glaciers of Alaska. Hike across the icy terrain, marvel at the deep blue crevasses, and even try your hand at ice climbing for an unforgettable experience.',
|
||||
locationName: 'Matanuska Glacier or Mendenhall Glacier',
|
||||
duration: 8,
|
||||
timeOfDay: TimeOfDay.morning,
|
||||
familyFriendly: false,
|
||||
price: 4,
|
||||
destinationRef: 'alaska',
|
||||
ref: 'glacier-trekking-and-ice-climbing',
|
||||
imageUrl:
|
||||
'https://storage.googleapis.com/tripedia-images/activities/alaska_glacier-trekking-and-ice-climbing.jpg',
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
if (ref == kBooking.destination.ref) {
|
||||
return Result.ok([kActivity]);
|
||||
}
|
||||
|
||||
return Result.ok([]);
|
||||
}
|
||||
|
||||
@override
|
||||
AuthHeaderProvider? authHeaderProvider;
|
||||
|
||||
@override
|
||||
Future<Result<BookingApiModel>> getBooking(int id) async {
|
||||
return Result.ok(kBookingApiModel);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<BookingApiModel>>> getBookings() async {
|
||||
return Result.ok([kBookingApiModel]);
|
||||
}
|
||||
|
||||
List<BookingApiModel> bookings = [];
|
||||
|
||||
@override
|
||||
Future<Result<BookingApiModel>> postBooking(BookingApiModel booking) async {
|
||||
final bookingWithId = booking.copyWith(id: bookings.length);
|
||||
bookings.add(bookingWithId);
|
||||
return Result.ok(bookingWithId);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<UserApiModel>> getUser() async {
|
||||
return Result.ok(userApiModel);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> deleteBooking(int id) async {
|
||||
bookings.removeWhere((booking) => booking.id == id);
|
||||
return Result.ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// 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:compass_app/utils/result.dart';
|
||||
|
||||
class FakeAuthApiClient implements AuthApiClient {
|
||||
@override
|
||||
Future<Result<LoginResponse>> login(LoginRequest loginRequest) async {
|
||||
if (loginRequest.email == 'EMAIL' && loginRequest.password == 'PASSWORD') {
|
||||
return const Result.ok(LoginResponse(token: 'TOKEN', userId: '123'));
|
||||
}
|
||||
return Result.error(Exception('ERROR!'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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/shared_preferences_service.dart';
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
|
||||
class FakeSharedPreferencesService implements SharedPreferencesService {
|
||||
String? token;
|
||||
|
||||
@override
|
||||
Future<Result<String?>> fetchToken() async {
|
||||
return Result.ok(token);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> saveToken(String? token) async {
|
||||
this.token = token;
|
||||
return Result.ok(null);
|
||||
}
|
||||
}
|
||||
60
compass_app/app/testing/mocks.dart
Normal file
60
compass_app/app/testing/mocks.dart
Normal file
@@ -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 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
class MockGoRouter extends Mock implements GoRouter {}
|
||||
|
||||
class MockHttpClient extends Mock implements HttpClient {}
|
||||
|
||||
class MockHttpHeaders extends Mock implements HttpHeaders {}
|
||||
|
||||
class MockHttpClientRequest extends Mock implements HttpClientRequest {}
|
||||
|
||||
class MockHttpClientResponse extends Mock implements HttpClientResponse {}
|
||||
|
||||
extension HttpMethodMocks on MockHttpClient {
|
||||
void mockGet(String path, Object object) {
|
||||
when(() => get(any(), any(), path)).thenAnswer((invocation) {
|
||||
final request = MockHttpClientRequest();
|
||||
final response = MockHttpClientResponse();
|
||||
when(() => request.close()).thenAnswer((_) => Future.value(response));
|
||||
when(() => request.headers).thenReturn(MockHttpHeaders());
|
||||
when(() => response.statusCode).thenReturn(200);
|
||||
when(
|
||||
() => response.transform(utf8.decoder),
|
||||
).thenAnswer((_) => Stream.value(jsonEncode(object)));
|
||||
return Future.value(request);
|
||||
});
|
||||
}
|
||||
|
||||
void mockPost(String path, Object object, [int statusCode = 201]) {
|
||||
when(() => post(any(), any(), path)).thenAnswer((invocation) {
|
||||
final request = MockHttpClientRequest();
|
||||
final response = MockHttpClientResponse();
|
||||
when(() => request.close()).thenAnswer((_) => Future.value(response));
|
||||
when(() => request.headers).thenReturn(MockHttpHeaders());
|
||||
when(() => response.statusCode).thenReturn(statusCode);
|
||||
when(
|
||||
() => response.transform(utf8.decoder),
|
||||
).thenAnswer((_) => Stream.value(jsonEncode(object)));
|
||||
return Future.value(request);
|
||||
});
|
||||
}
|
||||
|
||||
void mockDelete(String path) {
|
||||
when(() => delete(any(), any(), path)).thenAnswer((invocation) {
|
||||
final request = MockHttpClientRequest();
|
||||
final response = MockHttpClientResponse();
|
||||
when(() => request.close()).thenAnswer((_) => Future.value(response));
|
||||
when(() => request.headers).thenReturn(MockHttpHeaders());
|
||||
when(() => response.statusCode).thenReturn(204);
|
||||
return Future.value(request);
|
||||
});
|
||||
}
|
||||
}
|
||||
18
compass_app/app/testing/models/activity.dart
Normal file
18
compass_app/app/testing/models/activity.dart
Normal file
@@ -0,0 +1,18 @@
|
||||
// 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/domain/models/activity/activity.dart';
|
||||
|
||||
const kActivity = Activity(
|
||||
description: 'DESCRIPTION',
|
||||
destinationRef: 'DESTINATION',
|
||||
duration: 3,
|
||||
familyFriendly: true,
|
||||
imageUrl: 'http://example.com/img.png',
|
||||
locationName: 'LOCATION NAME',
|
||||
name: 'NAME',
|
||||
price: 3,
|
||||
ref: 'REF',
|
||||
timeOfDay: TimeOfDay.afternoon,
|
||||
);
|
||||
33
compass_app/app/testing/models/booking.dart
Normal file
33
compass_app/app/testing/models/booking.dart
Normal file
@@ -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/api/model/booking/booking_api_model.dart';
|
||||
import 'package:compass_app/domain/models/booking/booking.dart';
|
||||
import 'package:compass_app/domain/models/booking/booking_summary.dart';
|
||||
|
||||
import 'activity.dart';
|
||||
import 'destination.dart';
|
||||
|
||||
final kBooking = Booking(
|
||||
startDate: DateTime(2024, 01, 01),
|
||||
endDate: DateTime(2024, 02, 12),
|
||||
destination: kDestination1,
|
||||
activity: [kActivity],
|
||||
);
|
||||
|
||||
final kBookingSummary = BookingSummary(
|
||||
id: 0,
|
||||
startDate: kBooking.startDate,
|
||||
endDate: kBooking.endDate,
|
||||
name: '${kDestination1.name}, ${kDestination1.continent}',
|
||||
);
|
||||
|
||||
final kBookingApiModel = BookingApiModel(
|
||||
id: 0,
|
||||
startDate: kBooking.startDate,
|
||||
endDate: kBooking.endDate,
|
||||
name: '${kDestination1.name}, ${kDestination1.continent}',
|
||||
destinationRef: kDestination1.ref,
|
||||
activitiesRef: [kActivity.ref],
|
||||
);
|
||||
25
compass_app/app/testing/models/destination.dart
Normal file
25
compass_app/app/testing/models/destination.dart
Normal file
@@ -0,0 +1,25 @@
|
||||
// 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/domain/models/destination/destination.dart';
|
||||
|
||||
const kDestination1 = Destination(
|
||||
ref: 'ref1',
|
||||
name: 'name1',
|
||||
country: 'country1',
|
||||
continent: 'Europe',
|
||||
knownFor: 'knownFor1',
|
||||
tags: ['tags1'],
|
||||
imageUrl: 'imageUrl1',
|
||||
);
|
||||
|
||||
const kDestination2 = Destination(
|
||||
ref: 'ref2',
|
||||
name: 'name2',
|
||||
country: 'country2',
|
||||
continent: 'Europe',
|
||||
knownFor: 'knownFor2',
|
||||
tags: ['tags2'],
|
||||
imageUrl: 'imageUrl2',
|
||||
);
|
||||
15
compass_app/app/testing/models/user.dart
Normal file
15
compass_app/app/testing/models/user.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
// 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/model/user/user_api_model.dart';
|
||||
import 'package:compass_app/domain/models/user/user.dart';
|
||||
|
||||
const userApiModel = UserApiModel(
|
||||
id: 'ID',
|
||||
name: 'NAME',
|
||||
email: 'EMAIL',
|
||||
picture: 'assets/user.jpg',
|
||||
);
|
||||
|
||||
const user = User(name: 'NAME', picture: 'assets/user.jpg');
|
||||
9
compass_app/app/testing/utils/result.dart
Normal file
9
compass_app/app/testing/utils/result.dart
Normal file
@@ -0,0 +1,9 @@
|
||||
import 'package:compass_app/utils/result.dart';
|
||||
|
||||
extension ResultCast<T> on Result<T> {
|
||||
/// Convenience method to cast to Ok
|
||||
Ok<T> get asOk => this as Ok<T>;
|
||||
|
||||
/// Convenience method to cast to Error
|
||||
Error get asError => this as Error<T>;
|
||||
}
|
||||
Reference in New Issue
Block a user