|
|
|
import 'package:compass_app/domain/models/itinerary_config/itinerary_config.dart';
|
|
|
|
import 'package:compass_app/ui/results/view_models/results_viewmodel.dart';
|
|
|
|
import 'package:compass_app/ui/results/widgets/results_screen.dart';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
Compass App: Add "Activities", "Itinerary Config" and MVVM Commands (#2366)
Part of the WIP for the Compass App example. Merge to `compass-app`.
This PR introduces:
- A new feature for Activities (UI unfinished).
- A repository for the current Itinerary Configuration.
- A `Command` utils class to be used in View Models.
**Activities**
- PR adds the `compass_app/app/assets/activities.json` (large file!)
- Created `ActivityRepository` with local and remote implementation.
- Added `getActivitiesByDestination` to `ApiClient`
- Added `Activity` data model
- Created `ActivitiesScreen` and `ActivitiesViewModel`.
- WIP: Decided to finish the UI later due to the size the PR was taking.
- WIP: Server implementation for Activities will be completed in another
PR.
**Itinerary Configuration**
- Created the `ItineraryConfigRepository` with an "in-memory"
implementation. (local database or shared preferences could potentially
be implemented too)
- Refactored the way screens share data, instead of passing data using
the navigator query parameters, the screens store the state (the
itinerary configuration) in this repository, and load it when the screen
is opened.
- This allows to navigate between screens, back and forth, and keep the
selection of data the user made.
**Commands**
- To handle button taps and other running actions.
- Encapsulates an action, exposes the running state (to show progress
indicators), and ensures that the action cannot execute if it is already
running (to avoid multiple taps on buttons).
- Two implementations included, one without arguments `Command0`, and
one that supports a single argument `Command1`.
- Commands also provide an `onComplete` callback, in case the UI needs
to do something when the action finished running (e.g. navigate).
- Tests are included.
**TODO in further PRs**
- Finish the Activities UI and continue implementing the app flow.
- Introduce an error handling solution.
- Move the data jsons into a common folder (maybe a package?) so they
can be shared between app and server and don't duplicate files.
**Screencast**
As it can be observed, the state of the screen is recovered from the
stored "itinerary config".
Note: Activites screen appears empty, the list is just printed on
terminal at the moment.
[Screencast from 2024-07-23
10-58-40.webm](https://github.com/user-attachments/assets/54805c66-2938-48dd-8f63-a26b1e88eab6)
## Pre-launch Checklist
- [x] I read the [Flutter Style Guide] _recently_, and have followed its
advice.
- [x] I signed the [CLA].
- [x] I read the [Contributors Guide].
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-devrel
channel on [Discord].
<!-- Links -->
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md
[CLA]: https://cla.developers.google.com/
[Discord]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md
[Contributors Guide]:
https://github.com/flutter/samples/blob/main/CONTRIBUTING.md
7 months ago
|
|
|
import 'package:mocktail/mocktail.dart';
|
|
|
|
import 'package:mocktail_image_network/mocktail_image_network.dart';
|
|
|
|
|
[Compass App] Booking screen (#2380)
This PR adds the Booking screen at the end of the main app flow.
After the user selects `Activity`s, these get stored in the
`ItineraryConfig` and then the user navigates to the `BookingScreen`.
In the `BookingScreen`, a `Booking` is generated with the
`BookingCreateComponent`.
This component communicates with multiple repositories, and it is a bit
more complex than the average view model, something that we want to show
as discussed in the previous PRs.
<details>
<summary>Screenshots</summary>


</details>
In the `BookingScreen`, the user can tap on "share trip" which displays
the OS share sheet functionality. This uses the plugin `share_plus`, but
the functionality is also wrapped in the `BookingShareComponent`, which
takes a `Booking` object and creates a shareable string, then calls to
the `Share.share()` method from `share_plus`. But the `share_plus`
dependency is also injected into the `BookingShareComponent`, allowing
us to unit test without plugin dependencies.
This is an example of a shared booking to instant messaging:

**TODO**
- I want to take a look at the whole experience on mobile, as I noticed
some inconsistent UI and navigation issues that I couldn't see on
Desktop. I will submit those in a new PR.
- We also talked about user authentication in the design document. I
will work on that once we are happy with the main app flow.
## Pre-launch Checklist
- [x] I read the [Flutter Style Guide] _recently_, and have followed its
advice.
- [x] I signed the [CLA].
- [x] I read the [Contributors Guide].
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-devrel
channel on [Discord].
<!-- Links -->
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md
[CLA]: https://cla.developers.google.com/
[Discord]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md
[Contributors Guide]:
https://github.com/flutter/samples/blob/main/CONTRIBUTING.md
6 months ago
|
|
|
import '../../../testing/app.dart';
|
|
|
|
import '../../../testing/fakes/repositories/fake_destination_repository.dart';
|
|
|
|
import '../../../testing/fakes/repositories/fake_itinerary_config_repository.dart';
|
|
|
|
import '../../../testing/mocks.dart';
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
group('ResultsScreen widget tests', () {
|
Compass App: Add "Activities", "Itinerary Config" and MVVM Commands (#2366)
Part of the WIP for the Compass App example. Merge to `compass-app`.
This PR introduces:
- A new feature for Activities (UI unfinished).
- A repository for the current Itinerary Configuration.
- A `Command` utils class to be used in View Models.
**Activities**
- PR adds the `compass_app/app/assets/activities.json` (large file!)
- Created `ActivityRepository` with local and remote implementation.
- Added `getActivitiesByDestination` to `ApiClient`
- Added `Activity` data model
- Created `ActivitiesScreen` and `ActivitiesViewModel`.
- WIP: Decided to finish the UI later due to the size the PR was taking.
- WIP: Server implementation for Activities will be completed in another
PR.
**Itinerary Configuration**
- Created the `ItineraryConfigRepository` with an "in-memory"
implementation. (local database or shared preferences could potentially
be implemented too)
- Refactored the way screens share data, instead of passing data using
the navigator query parameters, the screens store the state (the
itinerary configuration) in this repository, and load it when the screen
is opened.
- This allows to navigate between screens, back and forth, and keep the
selection of data the user made.
**Commands**
- To handle button taps and other running actions.
- Encapsulates an action, exposes the running state (to show progress
indicators), and ensures that the action cannot execute if it is already
running (to avoid multiple taps on buttons).
- Two implementations included, one without arguments `Command0`, and
one that supports a single argument `Command1`.
- Commands also provide an `onComplete` callback, in case the UI needs
to do something when the action finished running (e.g. navigate).
- Tests are included.
**TODO in further PRs**
- Finish the Activities UI and continue implementing the app flow.
- Introduce an error handling solution.
- Move the data jsons into a common folder (maybe a package?) so they
can be shared between app and server and don't duplicate files.
**Screencast**
As it can be observed, the state of the screen is recovered from the
stored "itinerary config".
Note: Activites screen appears empty, the list is just printed on
terminal at the moment.
[Screencast from 2024-07-23
10-58-40.webm](https://github.com/user-attachments/assets/54805c66-2938-48dd-8f63-a26b1e88eab6)
## Pre-launch Checklist
- [x] I read the [Flutter Style Guide] _recently_, and have followed its
advice.
- [x] I signed the [CLA].
- [x] I read the [Contributors Guide].
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-devrel
channel on [Discord].
<!-- Links -->
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md
[CLA]: https://cla.developers.google.com/
[Discord]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md
[Contributors Guide]:
https://github.com/flutter/samples/blob/main/CONTRIBUTING.md
7 months ago
|
|
|
late MockGoRouter goRouter;
|
|
|
|
late ResultsViewModel viewModel;
|
|
|
|
|
|
|
|
setUp(() {
|
|
|
|
viewModel = ResultsViewModel(
|
|
|
|
destinationRepository: FakeDestinationRepository(),
|
|
|
|
itineraryConfigRepository: FakeItineraryConfigRepository(
|
|
|
|
itineraryConfig: ItineraryConfig(
|
|
|
|
continent: 'Europe',
|
|
|
|
startDate: DateTime(2024, 01, 01),
|
|
|
|
endDate: DateTime(2024, 01, 31),
|
|
|
|
guests: 2,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
goRouter = MockGoRouter();
|
|
|
|
});
|
|
|
|
|
|
|
|
Future<void> loadScreen(WidgetTester tester) async {
|
[Compass App] Booking screen (#2380)
This PR adds the Booking screen at the end of the main app flow.
After the user selects `Activity`s, these get stored in the
`ItineraryConfig` and then the user navigates to the `BookingScreen`.
In the `BookingScreen`, a `Booking` is generated with the
`BookingCreateComponent`.
This component communicates with multiple repositories, and it is a bit
more complex than the average view model, something that we want to show
as discussed in the previous PRs.
<details>
<summary>Screenshots</summary>


</details>
In the `BookingScreen`, the user can tap on "share trip" which displays
the OS share sheet functionality. This uses the plugin `share_plus`, but
the functionality is also wrapped in the `BookingShareComponent`, which
takes a `Booking` object and creates a shareable string, then calls to
the `Share.share()` method from `share_plus`. But the `share_plus`
dependency is also injected into the `BookingShareComponent`, allowing
us to unit test without plugin dependencies.
This is an example of a shared booking to instant messaging:

**TODO**
- I want to take a look at the whole experience on mobile, as I noticed
some inconsistent UI and navigation issues that I couldn't see on
Desktop. I will submit those in a new PR.
- We also talked about user authentication in the design document. I
will work on that once we are happy with the main app flow.
## Pre-launch Checklist
- [x] I read the [Flutter Style Guide] _recently_, and have followed its
advice.
- [x] I signed the [CLA].
- [x] I read the [Contributors Guide].
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-devrel
channel on [Discord].
<!-- Links -->
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md
[CLA]: https://cla.developers.google.com/
[Discord]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md
[Contributors Guide]:
https://github.com/flutter/samples/blob/main/CONTRIBUTING.md
6 months ago
|
|
|
await testApp(
|
|
|
|
tester,
|
|
|
|
ResultsScreen(viewModel: viewModel),
|
|
|
|
goRouter: goRouter,
|
Compass App: Add "Activities", "Itinerary Config" and MVVM Commands (#2366)
Part of the WIP for the Compass App example. Merge to `compass-app`.
This PR introduces:
- A new feature for Activities (UI unfinished).
- A repository for the current Itinerary Configuration.
- A `Command` utils class to be used in View Models.
**Activities**
- PR adds the `compass_app/app/assets/activities.json` (large file!)
- Created `ActivityRepository` with local and remote implementation.
- Added `getActivitiesByDestination` to `ApiClient`
- Added `Activity` data model
- Created `ActivitiesScreen` and `ActivitiesViewModel`.
- WIP: Decided to finish the UI later due to the size the PR was taking.
- WIP: Server implementation for Activities will be completed in another
PR.
**Itinerary Configuration**
- Created the `ItineraryConfigRepository` with an "in-memory"
implementation. (local database or shared preferences could potentially
be implemented too)
- Refactored the way screens share data, instead of passing data using
the navigator query parameters, the screens store the state (the
itinerary configuration) in this repository, and load it when the screen
is opened.
- This allows to navigate between screens, back and forth, and keep the
selection of data the user made.
**Commands**
- To handle button taps and other running actions.
- Encapsulates an action, exposes the running state (to show progress
indicators), and ensures that the action cannot execute if it is already
running (to avoid multiple taps on buttons).
- Two implementations included, one without arguments `Command0`, and
one that supports a single argument `Command1`.
- Commands also provide an `onComplete` callback, in case the UI needs
to do something when the action finished running (e.g. navigate).
- Tests are included.
**TODO in further PRs**
- Finish the Activities UI and continue implementing the app flow.
- Introduce an error handling solution.
- Move the data jsons into a common folder (maybe a package?) so they
can be shared between app and server and don't duplicate files.
**Screencast**
As it can be observed, the state of the screen is recovered from the
stored "itinerary config".
Note: Activites screen appears empty, the list is just printed on
terminal at the moment.
[Screencast from 2024-07-23
10-58-40.webm](https://github.com/user-attachments/assets/54805c66-2938-48dd-8f63-a26b1e88eab6)
## Pre-launch Checklist
- [x] I read the [Flutter Style Guide] _recently_, and have followed its
advice.
- [x] I signed the [CLA].
- [x] I read the [Contributors Guide].
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-devrel
channel on [Discord].
<!-- Links -->
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md
[CLA]: https://cla.developers.google.com/
[Discord]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md
[Contributors Guide]:
https://github.com/flutter/samples/blob/main/CONTRIBUTING.md
7 months ago
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
testWidgets('should load screen', (WidgetTester tester) async {
|
|
|
|
await mockNetworkImages(() async {
|
|
|
|
await loadScreen(tester);
|
|
|
|
expect(find.byType(ResultsScreen), findsOneWidget);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
testWidgets('should display destination', (WidgetTester tester) async {
|
|
|
|
await mockNetworkImages(() async {
|
|
|
|
await loadScreen(tester);
|
|
|
|
|
|
|
|
// Wait for list to load
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
// Note: Name is converted to uppercase
|
|
|
|
expect(find.text('NAME1'), findsOneWidget);
|
|
|
|
expect(find.text('tags1'), findsOneWidget);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
Compass App: Add "Activities", "Itinerary Config" and MVVM Commands (#2366)
Part of the WIP for the Compass App example. Merge to `compass-app`.
This PR introduces:
- A new feature for Activities (UI unfinished).
- A repository for the current Itinerary Configuration.
- A `Command` utils class to be used in View Models.
**Activities**
- PR adds the `compass_app/app/assets/activities.json` (large file!)
- Created `ActivityRepository` with local and remote implementation.
- Added `getActivitiesByDestination` to `ApiClient`
- Added `Activity` data model
- Created `ActivitiesScreen` and `ActivitiesViewModel`.
- WIP: Decided to finish the UI later due to the size the PR was taking.
- WIP: Server implementation for Activities will be completed in another
PR.
**Itinerary Configuration**
- Created the `ItineraryConfigRepository` with an "in-memory"
implementation. (local database or shared preferences could potentially
be implemented too)
- Refactored the way screens share data, instead of passing data using
the navigator query parameters, the screens store the state (the
itinerary configuration) in this repository, and load it when the screen
is opened.
- This allows to navigate between screens, back and forth, and keep the
selection of data the user made.
**Commands**
- To handle button taps and other running actions.
- Encapsulates an action, exposes the running state (to show progress
indicators), and ensures that the action cannot execute if it is already
running (to avoid multiple taps on buttons).
- Two implementations included, one without arguments `Command0`, and
one that supports a single argument `Command1`.
- Commands also provide an `onComplete` callback, in case the UI needs
to do something when the action finished running (e.g. navigate).
- Tests are included.
**TODO in further PRs**
- Finish the Activities UI and continue implementing the app flow.
- Introduce an error handling solution.
- Move the data jsons into a common folder (maybe a package?) so they
can be shared between app and server and don't duplicate files.
**Screencast**
As it can be observed, the state of the screen is recovered from the
stored "itinerary config".
Note: Activites screen appears empty, the list is just printed on
terminal at the moment.
[Screencast from 2024-07-23
10-58-40.webm](https://github.com/user-attachments/assets/54805c66-2938-48dd-8f63-a26b1e88eab6)
## Pre-launch Checklist
- [x] I read the [Flutter Style Guide] _recently_, and have followed its
advice.
- [x] I signed the [CLA].
- [x] I read the [Contributors Guide].
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-devrel
channel on [Discord].
<!-- Links -->
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md
[CLA]: https://cla.developers.google.com/
[Discord]:
https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md
[Contributors Guide]:
https://github.com/flutter/samples/blob/main/CONTRIBUTING.md
7 months ago
|
|
|
testWidgets('should tap and navigate to activities',
|
|
|
|
(WidgetTester tester) async {
|
|
|
|
await mockNetworkImages(() async {
|
|
|
|
await loadScreen(tester);
|
|
|
|
|
|
|
|
// Wait for list to load
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
// warnIfMissed false because false negative
|
|
|
|
await tester.tap(find.text('NAME1'), warnIfMissed: false);
|
|
|
|
|
|
|
|
verify(() => goRouter.go('/activities')).called(1);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|