App-DrivePlayer

 view release on metacpan or  search on metacpan

t/unit/Test/DrivePlayer/Player.pm  view on Meta::CPAN


    # Simulate stale token by backdating the token_time
    $p->_token_time($p->_token_time - 4000);

    $p->_bearer_token();
    is $call_count, 2, 'auth->headers called again after token expires';
    is $p->_token, 'Bearer token_call_2', 'new token returned after refresh';
}

sub bearer_token_clears_auth_cache : Tests(1) {
    my ($self) = @_;

    # Verify that {headers} is nil at the moment headers() is called, proving
    # that the code does `delete $auth->{headers}` before calling headers().
    my $was_nil_on_call;
    my $auth = fake_auth(token => 'Bearer fresh_token');
    $auth->{headers} = ['Authorization', 'Bearer stale_cached'];

    $self->_mock('clear_check', 'Test::DrivePlayer::MockAuth', 'headers', sub {
        my ($a) = @_;
        $was_nil_on_call = !defined $a->{headers};
        $a->{headers} = ['Authorization', $a->{token}];
        return $a->{headers};
    });

    my $p = App::DrivePlayer::Player->new(auth => $auth);
    $p->_token_time(time() - 4000);
    $p->_token('Bearer stale');
    $p->_bearer_token();

    ok $was_nil_on_call, 'auth->{headers} cleared before re-fetching token';
}

# ---- State transitions ----

sub state_transitions : Tests(6) {
    my ($self) = @_;

    my @state_changes;
    my $p = fake_player(
        on_state_change => sub { push @state_changes, $_[0] }
    );

    is $p->state, 'stop', 'initial state stop';

    # Manually drive state transitions without spawning mpv
    $p->_set_state('play');
    is $p->state, 'play', 'state set to play';
    is $state_changes[-1], 'play', 'on_state_change fired for play';

    $p->_set_state('pause');
    is $p->state, 'pause', 'state set to pause';
    is $state_changes[-1], 'pause', 'on_state_change fired for pause';

    # Setting same state should not fire callback again
    my $prev_count = scalar @state_changes;
    $p->_set_state('pause');
    is scalar @state_changes, $prev_count, 'on_state_change not fired for same state';
}

sub on_state_change_not_required : Tests(1) {
    my ($self) = @_;

    my $p = fake_player();
    lives_ok { $p->_set_state('play') } '_set_state lives without on_state_change callback';
}

# ---- End-of-file handling ----

sub handle_end_file_eof : Tests(3) {
    my ($self) = @_;

    my $track_ended = 0;
    my @state_changes;

    my $p = fake_player(
        on_track_end    => sub { $track_ended++ },
        on_state_change => sub { push @state_changes, $_[0] },
    );

    $p->_set_state('play');
    $p->_handle_end_file({ event => 'end-file', reason => 'eof' });

    is $p->state, 'stop',   'state becomes stop on eof';
    is $track_ended, 1,     'on_track_end fired on eof';
    is $state_changes[-1], 'stop', 'on_state_change fired with stop';
}

sub handle_end_file_error : Tests(2) {
    my ($self) = @_;

    # 'error' means the stream died mid-play (transient network failure,
    # Drive 4xx/5xx, token expiry).  We advance, same as 'eof'.
    my $track_ended = 0;
    my $p = fake_player(on_track_end => sub { $track_ended++ });
    $p->_set_state('play');

    $p->_handle_end_file({ event => 'end-file', reason => 'error' });
    is $track_ended, 1,   'on_track_end fired for error reason';
    is $p->state,    'stop', 'state becomes stop on error';
}

sub handle_end_file_stop_reason : Tests(2) {
    my ($self) = @_;

    # 'stop' fires for user-initiated stop AND for loadfile-replace
    # pre-empting the current track.  We must NOT advance on it, otherwise
    # pressing Next / Stop would trigger phantom skips.
    my $track_ended = 0;
    my $p = fake_player(on_track_end => sub { $track_ended++ });
    $p->_set_state('play');

    $p->_handle_end_file({ event => 'end-file', reason => 'stop' });
    is $track_ended, 0,    'on_track_end NOT fired for stop reason';
    is $p->state,    'play', 'state unchanged for stop reason';
}

sub handle_end_file_quit_reason : Tests(2) {
    my ($self) = @_;

    # 'quit' is emitted when mpv itself is shutting down — ignore.



( run in 3.828 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )