summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xlib/Travelynx.pm17
-rw-r--r--lib/Travelynx/Command/database.pm14
-rw-r--r--t/r-negative-delay.t94
-rw-r--r--templates/_history_stats.html.ep10
4 files changed, 129 insertions, 6 deletions
diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm
index 32b6b6d..a5dbcb8 100755
--- a/lib/Travelynx.pm
+++ b/lib/Travelynx.pm
@@ -2781,7 +2781,7 @@ sub startup {
}
$next_departure = $journey->{rt_dep_ts};
}
- return {
+ my $ret = {
km_route => $km_route,
km_beeline => $km_beeline,
num_trains => $num_trains,
@@ -2793,6 +2793,21 @@ sub startup {
delay_arr => $delay_arr,
inconsistencies => \@inconsistencies,
};
+ for my $key (
+ qw(min_travel_sched min_travel_real min_interchange_real delay_dep delay_arr)
+ )
+ {
+ my $strf_key = $key . '_strf';
+ my $value = $ret->{$key};
+ $ret->{$strf_key} = q{};
+ if ( $ret->{$key} < 0 ) {
+ $ret->{$strf_key} .= '-';
+ $value *= -1;
+ }
+ $ret->{$strf_key}
+ .= sprintf( '%02d:%02d', $value / 60, $value % 60 );
+ }
+ return $ret;
}
);
diff --git a/lib/Travelynx/Command/database.pm b/lib/Travelynx/Command/database.pm
index e92dd4b..a257b8b 100644
--- a/lib/Travelynx/Command/database.pm
+++ b/lib/Travelynx/Command/database.pm
@@ -1038,6 +1038,20 @@ my @migrations = (
}
);
},
+
+ # v22 -> v23
+ # 1.18.1 fixes handling of negative cumulative arrival/departure delays
+ # and introduces additional statistics entries with pre-formatted duration
+ # strings while at it. Old cache entries lack those.
+ sub {
+ my ($db) = @_;
+ $db->query(
+ qq{
+ truncate journey_stats;
+ update schema_version set version = 23;
+ }
+ );
+ },
);
sub setup_db {
diff --git a/t/r-negative-delay.t b/t/r-negative-delay.t
new file mode 100644
index 0000000..a2818c5
--- /dev/null
+++ b/t/r-negative-delay.t
@@ -0,0 +1,94 @@
+#!/usr/bin/env perl
+use Mojo::Base -strict;
+
+# Regression test: handle negative cumulative arrival / departure delay
+
+use Test::More;
+use Test::Mojo;
+
+# Include application
+use FindBin;
+require "$FindBin::Bin/../index.pl";
+
+my $t = Test::Mojo->new('Travelynx');
+
+if ( not $t->app->config->{db} ) {
+ plan( skip_all => 'No database configured' );
+}
+
+$t->app->pg->db->query(
+ 'drop schema if exists travelynx_regr_negative_delay cascade');
+$t->app->pg->db->query('create schema travelynx_regr_negative_delay');
+$t->app->pg->db->query('set search_path to travelynx_regr_negative_delay');
+$t->app->pg->on(
+ connection => sub {
+ my ( $pg, $dbh ) = @_;
+ $dbh->do('set search_path to travelynx_regr_negative_delay');
+ }
+);
+
+$t->app->config->{mail}->{disabled} = 1;
+
+$t->app->start( 'database', 'migrate' );
+
+my $csrf_token
+ = $t->ua->get('/register')->res->dom->at('input[name=csrf_token]')
+ ->attr('value');
+
+# Successful registration
+$t->post_ok(
+ '/register' => form => {
+ csrf_token => $csrf_token,
+ user => 'someone',
+ email => 'foo@example.org',
+ password => 'foofoofoo',
+ password2 => 'foofoofoo',
+ }
+);
+$t->status_is(200)->content_like(qr{Verifizierungslink});
+
+my $res = $t->app->pg->db->select( 'users', ['id'], { name => 'someone' } );
+my $uid = $res->hash->{id};
+$res = $t->app->pg->db->select( 'pending_registrations', ['token'],
+ { user_id => $uid } );
+my $token = $res->hash->{token};
+
+# Successful verification
+$t->get_ok("/reg/${uid}/${token}");
+$t->status_is(200)->content_like(qr{freigeschaltet});
+
+# Successful login
+$t->post_ok(
+ '/login' => form => {
+ csrf_token => $csrf_token,
+ user => 'someone',
+ password => 'foofoofoo',
+ }
+);
+$t->status_is(302)->header_is( location => '/' );
+
+$csrf_token
+ = $t->ua->get('/journey/add')->res->dom->at('input[name=csrf_token]')
+ ->attr('value');
+$t->post_ok(
+ '/journey/add' => form => {
+ csrf_token => $csrf_token,
+ action => 'save',
+ train => 'RE 42 11238',
+ dep_station => 'EMST',
+ sched_departure => '16.10.2018 17:36',
+ rt_departure => '16.10.2018 17:35',
+ arr_station => 'EG',
+ sched_arrival => '16.10.2018 18:34',
+ rt_arrival => '16.10.2018 18:32',
+ }
+);
+$t->status_is(302)->header_is( location => '/journey/1' );
+
+$t->get_ok('/history/2018/10')->status_is(200)->content_like(qr{62 km})
+ ->content_like(qr{00:57 Stunden})->content_like(qr{nach Fahrplan: 00:58})
+ ->content_like(qr{Bei Abfahrt: -00:01 Stunden})
+ ->content_like(qr{Bei Ankunft: -00:02 Stunden});
+
+$t->app->pg->db->query('drop schema travelynx_regr_negative_delay cascade');
+done_testing();
diff --git a/templates/_history_stats.html.ep b/templates/_history_stats.html.ep
index 8197ed1..d6c7979 100644
--- a/templates/_history_stats.html.ep
+++ b/templates/_history_stats.html.ep
@@ -39,17 +39,17 @@
</tr>
<tr>
<th scope="row">Fahrtzeit</th>
- <td><%= sprintf('%02d:%02d', $stats->{min_travel_real} / 60, $stats->{min_travel_real} % 60) %> Stunden
- (nach Fahrplan: <%= sprintf('%02d:%02d', $stats->{min_travel_sched} / 60, $stats->{min_travel_sched} % 60) %>)<td>
+ <td><%= $stats->{min_travel_real_strf} %> Stunden
+ (nach Fahrplan: <%= $stats->{min_travel_sched_strf} %>)<td>
</tr>
<tr>
<th scope="row">Wartezeit (nur Umstiege)</th>
- <td><%= sprintf('%02d:%02d', $stats->{min_interchange_real} / 60, $stats->{min_interchange_real} % 60) %> Stunden
+ <td><%= $stats->{min_interchange_real_strf} %> Stunden
</tr>
<tr>
<th scope="row">Kumulierte Verspätung</th>
- <td>Bei Abfahrt: <%= sprintf('%02d:%02d', $stats->{delay_dep} / 60, $stats->{delay_dep} % 60) %> Stunden<br/>
- Bei Ankunft: <%= sprintf('%02d:%02d', $stats->{delay_arr} / 60, $stats->{delay_arr} % 60) %> Stunden</td>
+ <td>Bei Abfahrt: <%= $stats->{delay_dep_strf} %> Stunden<br/>
+ Bei Ankunft: <%= $stats->{delay_arr_strf} %> Stunden</td>
</tr>
</table>
</div>