Skip to content

Commit

Permalink
Feat/routing (#17)
Browse files Browse the repository at this point in the history
* feat: add router class and add placeholder subpages

* feat: add routing methods at correct places in code and some placeholder stuff

* feat: add tests for routing in the pages itself

* feat: add app_router unit tests
  • Loading branch information
MhouneyLH authored Sep 3, 2023
1 parent 41c8111 commit a0200b4
Show file tree
Hide file tree
Showing 12 changed files with 395 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:deskify/features/presentation/router/app_router.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

Expand Down Expand Up @@ -165,7 +166,9 @@ class _AddDeskPageState extends State<AddDeskPage> {
Theme.of(context).colorScheme.primary,
),
),
onPressed: () {},
onPressed: () {
Navigator.of(context).pushNamed(AppRouter.addDeskAddPresetPath);
},
),
);
}
Expand Down Expand Up @@ -204,7 +207,9 @@ class _AddDeskPageState extends State<AddDeskPage> {
subtitle: '${preset.targetHeight.toStringAsFixed(2)} $deskHeightMetric',
iconAtStart: const Icon(Icons.height),
iconAtEnd: const Icon(Icons.edit),
onPressedIconAtEnd: () {},
onPressedIconAtEnd: () {
Navigator.of(context).pushNamed(AppRouter.addDeskEditPresetPath);
},
);

interactionCards.add(card);
Expand Down
18 changes: 14 additions & 4 deletions lib/features/presentation/pages/home_page/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../domain/entities/desk.dart';
import '../../../domain/entities/preset.dart';
import '../../bloc/desk/desk_bloc.dart';
import '../../router/app_router.dart';
import '../../themes/theme.dart';
import '../../widgets/widgets.dart';
import 'desk_carousel_slider.dart';
Expand Down Expand Up @@ -45,7 +46,10 @@ class _HomePageState extends State<HomePage> {
key: const Key('analytics-desk-card-standing'),
title: 'Standing Time',
iconAtStart: const Icon(Icons.info),
onPressedCard: () {},
onPressedCard: () {
Navigator.of(context)
.pushNamed(AppRouter.homeStandingAnalyticsPath);
},
child: const LinearProgressIndicator(
value: 1.0,
),
Expand All @@ -55,7 +59,9 @@ class _HomePageState extends State<HomePage> {
key: const Key('analytics-desk-card-sitting'),
title: 'Sitting Time',
iconAtStart: const Icon(Icons.info),
onPressedCard: () {},
onPressedCard: () {
Navigator.of(context).pushNamed(AppRouter.homeSittingAnalyticsPath);
},
child: const LinearProgressIndicator(
value: 0.3,
),
Expand All @@ -77,7 +83,9 @@ class _HomePageState extends State<HomePage> {
key: const Key('others-desk-card-move'),
title: 'Move desk',
iconAtStart: const Icon(Icons.move_up),
onPressedCard: () {},
onPressedCard: () {
Navigator.of(context).pushNamed(AppRouter.homeMoveDeskPath);
},
),
],
);
Expand Down Expand Up @@ -211,7 +219,9 @@ class _HomePageState extends State<HomePage> {
iconAtStart: const Icon(Icons.height),
iconAtEnd: const Icon(Icons.settings),
onPressedCard: () {},
onPressedIconAtEnd: () {},
onPressedIconAtEnd: () {
Navigator.of(context).pushNamed(AppRouter.homeEditPresetPath);
},
);

presetCards.add(card);
Expand Down
39 changes: 39 additions & 0 deletions lib/features/presentation/router/app_router.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:deskify/features/presentation/subpages/subpages.dart';
import 'package:flutter/material.dart';

/// This class provides the routing of the subpages for the application.
///
/// The actual pages, which can be clicked in the BottomNavigationBar, are
/// defined in the [App] class.
class AppRouter {
static const String homeStandingAnalyticsPath = '/home/standing_analytics';
static const String homeSittingAnalyticsPath = '/home/sitting_analytics';
static const String homeAddPresetPath = '/home/add_preset';
static const String homeEditPresetPath = '/home/edit_preset';
static const String homeMoveDeskPath = '/home/move_desk';
static const String addDeskAddPresetPath = '/add_desk/add_preset';
static const String addDeskEditPresetPath = '/add_desk/edit_preset';

Route? onGenerateRoute(RouteSettings settings) {
switch (settings.name) {
//! HomePage
case homeStandingAnalyticsPath:
return MaterialPageRoute(builder: (_) => const AnalyticsPage());
case homeSittingAnalyticsPath:
return MaterialPageRoute(builder: (_) => const AnalyticsPage());
case homeAddPresetPath:
return MaterialPageRoute(builder: (_) => const PresetPage());
case homeEditPresetPath:
return MaterialPageRoute(builder: (_) => const PresetPage());
case homeMoveDeskPath:
return MaterialPageRoute(builder: (_) => const MoveDeskPage());
//! AddDeskPage
case addDeskAddPresetPath:
return MaterialPageRoute(builder: (_) => const PresetPage());
case addDeskEditPresetPath:
return MaterialPageRoute(builder: (_) => const PresetPage());
default:
return null;
}
}
}
20 changes: 20 additions & 0 deletions lib/features/presentation/subpages/analytics_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:flutter/material.dart';

class AnalyticsPage extends StatefulWidget {
const AnalyticsPage({super.key});

@override
State<AnalyticsPage> createState() => _AnalyticsPageState();
}

class _AnalyticsPageState extends State<AnalyticsPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Analytics Page'),
),
body: const Placeholder(),
);
}
}
20 changes: 20 additions & 0 deletions lib/features/presentation/subpages/move_desk_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:flutter/material.dart';

class MoveDeskPage extends StatefulWidget {
const MoveDeskPage({super.key});

@override
State<MoveDeskPage> createState() => _MoveDeskPageState();
}

class _MoveDeskPageState extends State<MoveDeskPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Move Desk Page'),
),
body: const Placeholder(),
);
}
}
20 changes: 20 additions & 0 deletions lib/features/presentation/subpages/preset_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:flutter/material.dart';

class PresetPage extends StatefulWidget {
const PresetPage({super.key});

@override
State<PresetPage> createState() => _PresetPageState();
}

class _PresetPageState extends State<PresetPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Preset Page'),
),
body: const Placeholder(),
);
}
}
3 changes: 3 additions & 0 deletions lib/features/presentation/subpages/subpages.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export 'analytics_page.dart';
export 'move_desk_page.dart';
export 'preset_page.dart';
11 changes: 8 additions & 3 deletions lib/injection_container.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get_it/get_it.dart';
import 'package:internet_connection_checker/internet_connection_checker.dart';

Expand All @@ -8,8 +7,8 @@ import 'features/data/data_sources/desk_remote_data_source.dart';
import 'features/data/repository/desk_repository_impl.dart';
import 'features/domain/repository/desk_repository.dart';
import 'features/domain/usecases/usecases.dart';
import 'features/presentation/bloc/app_bloc_observer.dart';
import 'features/presentation/bloc/desk/desk_bloc.dart';
import 'features/presentation/router/app_router.dart';

// sl = service locator
// using sl() is short for sl.call()
Expand All @@ -19,7 +18,10 @@ final sl = GetIt.instance;
Future<void> init() async {
//! Features
// Bloc
sl.registerLazySingleton<BlocObserver>(() => AppBlocObserver());
// actually I dont need it for now
// Bloc.observer = injection_container.sl();
// sl.registerLazySingleton<BlocObserver>(() => AppBlocObserver());

sl.registerFactory(() => DeskBloc(
createDeskUsecase: sl(),
getAllDesksUsecase: sl(),
Expand Down Expand Up @@ -49,6 +51,9 @@ Future<void> init() async {
sl.registerLazySingleton<NetworkInfo>(
() => NetworkInfoImpl(connectionChecker: sl()));

// routing
sl.registerLazySingleton(() => AppRouter());

//! External
sl.registerLazySingleton(() => InternetConnectionChecker());
sl.registerLazySingleton(() => FirebaseFirestore.instance);
Expand Down
17 changes: 11 additions & 6 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';

import 'app.dart';
import 'features/presentation/bloc/desk/desk_bloc.dart';
import 'features/presentation/router/app_router.dart';
import 'features/presentation/themes/theme.dart';
import 'injection_container.dart' as injection_container;

Expand All @@ -13,23 +14,26 @@ Future main() async {
await Firebase.initializeApp();
await injection_container.init();

// TODO: maybe this should be moved in injection_container.dart???
// actually I dont need it for now
// Bloc.observer = injection_container.sl();

runApp(
MultiBlocProvider(
providers: [
BlocProvider(create: (_) => injection_container.sl<DeskBloc>()),
],
child: const MainApp(),
child: MainApp(
appRouter: injection_container.sl(),
),
),
);
}

class MainApp extends StatelessWidget {
const MainApp({super.key});
final AppRouter appRouter;

const MainApp({
required this.appRouter,
super.key,
});

static const String title = 'Deskify';

@override
Expand All @@ -40,6 +44,7 @@ class MainApp extends StatelessWidget {
theme: ThemeSettings.lightTheme,
darkTheme: ThemeSettings.darkTheme,
home: const App(),
onGenerateRoute: (settings) => appRouter.onGenerateRoute(settings),
);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import 'package:deskify/core/core.dart';
import 'package:deskify/features/domain/entities/desk.dart';
import 'package:deskify/features/domain/entities/preset.dart';
import 'package:deskify/features/domain/repository/desk_repository.dart';
import 'package:deskify/features/domain/usecases/usecases.dart';
import 'package:deskify/features/presentation/bloc/desk/desk_bloc.dart';
import 'package:deskify/features/presentation/pages/add_desk_page/add_desk_page.dart';
import 'package:deskify/features/presentation/router/app_router.dart';
import 'package:deskify/features/presentation/subpages/subpages.dart';
import 'package:deskify/features/presentation/widgets/widgets.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
Expand All @@ -15,29 +15,13 @@ class MockDeskRepository extends Mock implements DeskRepository {}

void main() {
late MockDeskRepository mockDeskRepository;
late AppRouter appRouter;

setUp(() {
mockDeskRepository = MockDeskRepository();
appRouter = AppRouter();
});

final Desk tDesk = Desk(
id: '0',
name: 'test',
height: 0.0,
presets: const <Preset>[
Preset(
id: '0',
name: 'test',
targetHeight: 0.0,
),
Preset(
id: '1',
name: 'test',
targetHeight: 1.0,
),
],
);

Widget createWidgetUnderTest() {
return BlocProvider(
create: (context) => DeskBloc(
Expand All @@ -47,8 +31,9 @@ void main() {
updateDeskUsecase: UpdateDeskUsecase(repository: mockDeskRepository),
deleteDeskUsecase: DeleteDeskUsecase(repository: mockDeskRepository),
),
child: const MaterialApp(
home: Scaffold(
child: MaterialApp(
onGenerateRoute: (settings) => appRouter.onGenerateRoute(settings),
home: const Scaffold(
body: SingleChildScrollView(
child: AddDeskPage(),
),
Expand Down Expand Up @@ -190,19 +175,55 @@ void main() {
expect(find.byKey(const Key('presets-heading')), findsOneWidget);
});

testWidgets('List of Preset InteractionCards is displayed', (widgetTester) async {
testWidgets('List of Preset InteractionCards is displayed',
(widgetTester) async {
// act
await widgetTester.pumpWidget(createWidgetUnderTest());
// assert
expect(find.byType(InteractionCard), findsAtLeastNWidgets(2));
});

testWidgets(
'Tapping on the icon at the end of an element of the Preset Interaction Card List, navigates to PresetPage',
(widgetTester) async {
// arrange
await widgetTester.pumpWidget(createWidgetUnderTest());
// act
final InteractionCard addPresetButton = widgetTester
.widget<InteractionCard>(find.byKey(const Key('preset-card-0')));

// this is a workaround for the actual tap
// the normal .tap() method does not work correctly as it seems
// the tap cannot be executed, because the button is not visible, but actually it is...
addPresetButton.onPressedIconAtEnd!();
await widgetTester.pumpAndSettle();
// assert
expect(find.byType(PresetPage), findsOneWidget);
});

testWidgets('Add Preset button is displayed', (widgetTester) async {
// act
await widgetTester.pumpWidget(createWidgetUnderTest());
// assert
expect(find.byKey(const Key('add-preset-button')), findsOneWidget);
});

testWidgets('Tapping on the AddPresetButton, navigates to PresetPage',
(widgetTester) async {
// arrange
await widgetTester.pumpWidget(createWidgetUnderTest());
// act
final IconButton addPresetButton = widgetTester
.widget<IconButton>(find.byKey(const Key('add-preset-button')));

// this is a workaround for the actual tap
// the normal .tap() method does not work correctly as it seems
// the tap cannot be executed, because the button is not visible, but actually it is...
addPresetButton.onPressed!();
await widgetTester.pumpAndSettle();
// assert
expect(find.byType(PresetPage), findsOneWidget);
});
});

testWidgets('Add Desk button is displayed', (widgetTester) async {
Expand Down
Loading

0 comments on commit a0200b4

Please sign in to comment.