Skip to content

Commit

Permalink
feat: implement betriebspunktabfolge (#388)
Browse files Browse the repository at this point in the history
Co-authored-by: u221638 <[email protected]>
  • Loading branch information
Grodien and rawi-coding authored Nov 20, 2024
1 parent 3a725a8 commit 9f36786
Show file tree
Hide file tree
Showing 74 changed files with 1,629 additions and 266 deletions.
5 changes: 5 additions & 0 deletions das_client/assets/icons/icon_header_stop.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions das_client/assets/icons/icon_stop_on_request.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
119 changes: 110 additions & 9 deletions das_client/integration_test/test/train_journey_table_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import 'package:das_client/app/pages/journey/train_journey/widgets/table/cells/bracket_station_body.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/table/cells/route_cell_body.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/table/service_point_row.dart';
import 'package:das_client/app/pages/profile/profile_page.dart';
import 'package:design_system_flutter/design_system_flutter.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -40,24 +43,20 @@ void main() {
expect(scrollableFinder, findsOneWidget);

// check first train station
expect(find.text('ZUE'), findsOneWidget);
expect(find.text('Zürich HB'), findsOneWidget);

// Scroll to last train station
await tester.dragUntilVisible(
find.text('AAR'),
find.byType(ListView),
const Offset(0, -300)
);
await tester.dragUntilVisible(find.text('Aarau'), find.byType(ListView), const Offset(0, -300));
});

testWidgets('test fahrbild stays loaded after navigation', (tester) async {
testWidgets('test if train journey stays loaded after navigation', (tester) async {
await prepareAndStartApp(tester);

// load train journey by filling out train selection page
await _loadTrainJourney(tester, trainNumber: '4816');

// check first train station
expect(find.text('ZUE'), findsOneWidget);
expect(find.text('Zürich HB'), findsOneWidget);

await openDrawer(tester);
await tapElement(tester, find.text(l10n.w_navigation_drawer_profile_title));
Expand All @@ -69,7 +68,109 @@ void main() {
await tapElement(tester, find.text(l10n.w_navigation_drawer_fahrtinfo_title));

// check first train station is still visible
expect(find.text('ZUE'), findsOneWidget);
expect(find.text('Zürich HB'), findsOneWidget);
});

testWidgets('test both kilometres are displayed', (tester) async {
await prepareAndStartApp(tester);

// load train journey by filling out train selection page
await _loadTrainJourney(tester, trainNumber: '4816');

final scrollableFinder = find.byType(ListView);
expect(scrollableFinder, findsOneWidget);

final hardbruckeRow = findDASTableRowByText('Hardbrücke');
expect(hardbruckeRow, findsOneWidget);
expect(find.descendant(of: hardbruckeRow, matching: find.text('1.9')), findsOneWidget);
expect(find.descendant(of: hardbruckeRow, matching: find.text('23.5')), findsOneWidget);
});

testWidgets('test bracket stations is displayed correctly', (tester) async {
await prepareAndStartApp(tester);

// load train journey by filling out train selection page
await _loadTrainJourney(tester, trainNumber: '9999');

final bracketStationD = findDASTableRowByText('Klammerbahnhof D');
final bracketStationD1 = findDASTableRowByText('Klammerbahnhof D1');
expect(bracketStationD, findsOneWidget);
expect(bracketStationD1, findsOneWidget);

// check if the bracket station widget is displayed
final bracketStationDWidget =
find.descendant(of: bracketStationD, matching: find.byKey(BracketStationBody.bracketStationKey));
final bracketStationD1Widget =
find.descendant(of: bracketStationD1, matching: find.byKey(BracketStationBody.bracketStationKey));
expect(bracketStationDWidget, findsOneWidget);
expect(bracketStationD1Widget, findsOneWidget);

// check that the abbreviation is displayed correctly
expect(find.descendant(of: bracketStationDWidget, matching: find.text('D')), findsNothing);
expect(find.descendant(of: bracketStationD1Widget, matching: find.text('D')), findsOneWidget);
});

testWidgets('test halt on request is displayed correctly', (tester) async {
await prepareAndStartApp(tester);

// load train journey by filling out train selection page
await _loadTrainJourney(tester, trainNumber: '9999');

final stopOnDemandRow = findDASTableRowByText('Halt auf Verlangen C');
expect(stopOnDemandRow, findsOneWidget);

final stopOnRequestIcon =
find.descendant(of: stopOnDemandRow, matching: find.byKey(ServicePointRow.stopOnRequestKey));
expect(stopOnRequestIcon, findsOneWidget);

final stopOnRequestRoute =
find.descendant(of: stopOnDemandRow, matching: find.byKey(RouteCellBody.stopOnRequestKey));
final stopRoute = find.descendant(of: stopOnDemandRow, matching: find.byKey(RouteCellBody.stopKey));
expect(stopOnRequestRoute, findsOneWidget);
expect(stopRoute, findsNothing);
});

testWidgets('test route is displayed correctly', (tester) async {
await prepareAndStartApp(tester);

// load train journey by filling out train selection page
await _loadTrainJourney(tester, trainNumber: '9999');

final stopRouteRow = findDASTableRowByText('Bahnhof A');
final nonStoppingPassRouteRow = findDASTableRowByText('Haltestelle B');
expect(stopRouteRow, findsOneWidget);
expect(nonStoppingPassRouteRow, findsOneWidget);

// check stop circles
final stopRoute = find.descendant(of: stopRouteRow, matching: find.byKey(RouteCellBody.stopKey));
final nonStoppingPassRoute = find.descendant(of: nonStoppingPassRouteRow, matching: find.byKey(RouteCellBody.stopKey));
expect(stopRoute, findsOneWidget);
expect(nonStoppingPassRoute, findsNothing);

// check route start
final startStationRow = findDASTableRowByText('Bahnhof A');
final routeStart = find.descendant(of: startStationRow, matching: find.byKey(RouteCellBody.routeStartKey));
expect(routeStart, findsOneWidget);

// check route end
final endStationRow = findDASTableRowByText('Klammerbahnhof D1');
final routeEnd = find.descendant(of: endStationRow, matching: find.byKey(RouteCellBody.routeEndKey));
expect(routeEnd, findsOneWidget);
});

testWidgets('test halt is displayed italic', (tester) async {
await prepareAndStartApp(tester);

// load train journey by filling out train selection page
await _loadTrainJourney(tester, trainNumber: '4816');

final glanzenbergText = find
.byWidgetPredicate((it) => it is Text && it.data == 'Glanzenberg' && it.style?.fontStyle == FontStyle.italic);
expect(glanzenbergText, findsOneWidget);

final schlierenText = find
.byWidgetPredicate((it) => it is Text && it.data == 'Schlieren' && it.style?.fontStyle != FontStyle.italic);
expect(schlierenText, findsOneWidget);
});
});
}
Expand Down
2 changes: 1 addition & 1 deletion das_client/integration_test/test/train_journey_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ void main() {
await tester.pumpAndSettle();

// check if station is present
expect(find.text('SO_W'), findsOneWidget);
expect(find.text('Solothurn'), findsOneWidget);

await tester.pumpAndSettle();
});
Expand Down
5 changes: 5 additions & 0 deletions das_client/integration_test/util/test_utils.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:das_client/app/widgets/table/das_table.dart';
import 'package:design_system_flutter/design_system_flutter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
Expand All @@ -24,3 +25,7 @@ Finder findTextFieldByLabel(String label) {
final sbbTextField = find.byWidgetPredicate((widget) => widget is SBBTextField && widget.labelText == label);
return find.descendant(of: sbbTextField, matching: find.byType(TextField));
}

Finder findDASTableRowByText(String text) {
return find.ancestor(of: find.text(text), matching: find.byKey(DASTable.rowKey));
}
5 changes: 2 additions & 3 deletions das_client/lib/app/bloc/train_journey_cubit.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';

import 'package:das_client/app/model/ru.dart';
import 'package:das_client/model/journey/journey.dart';
import 'package:das_client/sfera/sfera_component.dart';
import 'package:das_client/util/error_code.dart';
import 'package:fimber/fimber.dart';
Expand All @@ -17,9 +18,7 @@ class TrainJourneyCubit extends Cubit<TrainJourneyState> {

final SferaService _sferaService;

Stream<JourneyProfile?> get journeyStream => _sferaService.journeyStream;

Stream<List<SegmentProfile>> get segmentStream => _sferaService.segmentStream;
Stream<Journey?> get journeyStream => _sferaService.journeyStream;

StreamSubscription? _stateSubscription;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import 'package:das_client/app/i18n/i18n.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/header/departure_authorization.dart';
import 'package:das_client/app/pages/journey/train_journey/widgets/header/radio_channel.dart';
import 'package:das_client/app/widgets/assets.dart';
import 'package:das_client/app/widgets/widget_extensions.dart';
import 'package:design_system_flutter/design_system_flutter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

class MainContainer extends StatelessWidget {
const MainContainer({super.key});
Expand Down Expand Up @@ -56,8 +58,7 @@ class MainContainer extends StatelessWidget {
height: 48.0,
child: Row(
children: [
// TODO: Replace with custom icon from figma
const Icon(SBBIcons.route_circle_end_small),
SvgPicture.asset(AppAssets.iconHeaderStop),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: sbbDefaultSpacing * 0.5),
Expand All @@ -71,27 +72,25 @@ class MainContainer extends StatelessWidget {
}

Widget _buttonArea() {
return Builder(
builder: (context) {
return Row(
children: [
SBBTertiaryButtonLarge(
label: context.l10n.p_train_journey_header_button_dark_theme,
icon: SBBIcons.moon_small,
onPressed: () {},
),
SBBTertiaryButtonLarge(
label: context.l10n.p_train_journey_header_button_pause,
icon: SBBIcons.pause_small,
onPressed: () {},
),
SBBIconButtonLarge(
icon: SBBIcons.context_menu_small,
onPressed: () {},
),
].withSpacing(width: sbbDefaultSpacing * 0.5),
);
}
);
return Builder(builder: (context) {
return Row(
children: [
SBBTertiaryButtonLarge(
label: context.l10n.p_train_journey_header_button_dark_theme,
icon: SBBIcons.moon_small,
onPressed: () {},
),
SBBTertiaryButtonLarge(
label: context.l10n.p_train_journey_header_button_pause,
icon: SBBIcons.pause_small,
onPressed: () {},
),
SBBIconButtonLarge(
icon: SBBIcons.context_menu_small,
onPressed: () {},
),
].withSpacing(width: sbbDefaultSpacing * 0.5),
);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ abstract class BaseRowBuilder extends DASTableRowBuilder {
this.defaultAlignment = Alignment.centerLeft,
this.rowColor,
this.isCurrentPosition = false,
this.isServicePointStop = false,
});

final double? kilometre;
final List<double>? kilometre;
final Alignment defaultAlignment;
final Color? rowColor;
final bool isServicePointStop;
final bool isCurrentPosition;

@override
Expand All @@ -41,13 +39,20 @@ abstract class BaseRowBuilder extends DASTableRowBuilder {
}

DASTableCell kilometreCell() {
if (kilometre == null) {
if (kilometre == null || kilometre!.isEmpty) {
return DASTableCell.empty();
}

var kilometreAsString = kilometre!.toStringAsFixed(3);
kilometreAsString = kilometreAsString.replaceAll(RegExp(r'0*$'), '');
return DASTableCell(child: Text(kilometreAsString), alignment: defaultAlignment);
return DASTableCell(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(kilometre![0].toStringAsFixed(1)),
if (kilometre!.length > 1) Text(kilometre![1].toStringAsFixed(1))
],
),
alignment: Alignment.centerLeft);
}

DASTableCell timeCell() {
Expand All @@ -58,10 +63,7 @@ abstract class BaseRowBuilder extends DASTableRowBuilder {
return DASTableCell(
padding: EdgeInsets.all(0.0),
alignment: null,
child: RouteCellBody(
showCircle: isServicePointStop,
showChevron: isCurrentPosition,
),
child: RouteCellBody(isCurrentPosition: isCurrentPosition),
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import 'package:das_client/model/journey/bracket_station.dart';
import 'package:design_system_flutter/design_system_flutter.dart';
import 'package:flutter/material.dart';

class BracketStationBody extends StatelessWidget {
static const Key bracketStationKey = Key('bracketStationKey');
static const double _bracketStationWidth = 16.0;
static const double _bracketStationFontSize = 12.0;

const BracketStationBody({
super.key,
required this.bracketStation,
required this.height
});

final BracketStation bracketStation;
final double height;

@override
Widget build(BuildContext context) {
return Positioned(
top: -sbbDefaultSpacing,
bottom: -sbbDefaultSpacing,
right: 0,
child: Container(
key: bracketStationKey,
height: height,
width: _bracketStationWidth,
color: SBBColors.black,
child: Align(
alignment: Alignment.center,
child: RotatedBox(
quarterTurns: -1,
child: Text(
bracketStation.mainStationAbbreviation ?? '',
style: SBBTextStyles.extraSmallBold.copyWith(
color: SBBColors.white,
fontSize: _bracketStationFontSize,
height: _bracketStationWidth / _bracketStationFontSize),
),
),
),
),
);
}
}
Loading

0 comments on commit 9f36786

Please sign in to comment.