File Coverage

File:blib/lib/TB2/EventHandler.pm
Coverage:97.1%

linestmtbrancondsubcode
1package TB2::EventHandler;
2
3
368
368
368
use TB2::Mouse ();
4
368
368
368
use TB2::Mouse::Role;
5with 'TB2::HasObjectID';
6
7our $VERSION = '1.005000_005';
8$VERSION = eval $VERSION; ## no critic (BuiltinFunctions::ProhibitStringyEval)
9
10
368
368
368
no TB2::Mouse::Role;
11
12
13 - 76
=head1 NAME

TB2::EventHandler - A role which handles events and results

=head1 SYNOPSIS

  package My::EventHandler;

  use TB2::Mouse;
  with "TB2::EventHandler";

  # handle_result() handles result events
  sub handle_result {
      my $self = shift;
      my($result, $ec) = @_;

      ...
  }

  # handle_comment() handles comment events... and so on
  sub handle_comment {
      my $self = shift;
      my($comment, $ec) = @_;

      ...
  }


  # handle_event() handles anything not handled by some other method
  sub handle_event  {
      my $self = shift;
      my($event, $ec) = @_;

      ....
  }

  no TB2::Mouse;


=head1 DESCRIPTION

An EventHandler is made known to an EventCoordinator which gives it
Events and Results to do whatever it wants with.  EventHandlers can be
used to record events for future use (such as
L<TB2::History>), to take an action like producing output
(such as L<TB2::Formatter>) or even modifying the event
itself.

=head1 METHODS

=head3 accept_event

    $handler->accept_event($event, $event_coordinator);

Pass an $event and the $event_coordinator managing it to the $handler.
The $handler will then pass them along to the appropriate handler
method based on the C<< $event->event_type >>.  If the appropriate
handler method does not exist, it will pass it to C<<handle_event>>.

This is the main interface to pass events to an EventHandler.  You
should I<not> pass events directly to handler methods as they may not
exist.

=cut
77
78our %type2method;
79sub accept_event {
80
19004
    my($self, $event, $ec) = @_;
81
82
19004
    my $type = $event->event_type;
83
19004
    my $method = $type2method{$type} ||= $self->_event_type2handle_method($type);
84
85
19004
    $self->can($method)
86          ? $self->$method($event, $ec)
87          : $self->handle_event($event, $ec);
88
89
18984
    return;
90}
91
92
93sub _event_type2handle_method {
94
1288
    my $self = shift;
95
1288
    my $type = shift;
96
97
1288
    my $method = "handle_".$type;
98
1288
    $method =~ s{\s}{_}g;
99
100
1288
    return $method;
101}
102
103
104 - 119
=head3 subtest_handler

    my $subtest_handler = $handler->subtest_handler($subtest_start_event);

When a subtest starts, the TestState will call C<subtest_handler> on
each EventHandler to get a handler for the subtest.  It will be passed
in the $subtest_start_event (see L<TB2::Event::SubtestStart>).

The provided method simply returns a new instance of the $handler's
class which should be sufficient for most handlers.

You may override this to, for example, configure the new instance.  Or
to return the same instance if you want a single instance to handle
all subtests.

=cut
120
121sub subtest_handler {
122
282
    my $self = shift;
123
282
    my $class = ref $self;
124
125
282
    return $class->new;
126}
127
128 - 169
=head3 object_id

    my $id = $thing->object_id;

Returns an identifier for this object unique to the running process.
The identifier is fairly simple and easily predictable.

See L<TB2::HasObjectID>

=head2 Event handlers

EventHandlers process events via event handler methods.  They are all
of the form C<< "handle_".$event->event_type >>.  So a "comment" event
is handled by C<< handle_comment >>.

Event handlers are all called like this:

    $handler->handle_thing($event, $event_coordinator);

$event is the event being handled.

$event_coordinator is the coordinator which is managing the $event.
This allows a handler to issue their own Events or access history via
C<< $ec->history >>.

A handler is allowed to alter the $event.  Those changes will be
visible to other EventHandlers down the line.

Event handler methods should B<not> be called directly.  Instead use
L<accept_event>.


=head3 handle_event

    $event_handler->handle_event($event, $event_coordinator);

This handles any event not handled by a more specific event handler
(such as handle_result).

By default it does nothing.

=cut
170
171
5510
sub handle_event {}
172
173
174 - 208
=head1 EXAMPLE

Here is an example of an EventHandler which formats the results as a
stream of pluses and minuses.

    package My::Formatter::PlusMinus;

    use TB2::Mouse;

    # This provides write(), otherwise it's a normal EventHandler
    extends 'TB2::Formatter';

    # Output a newline when we're done testing.
    sub handle_test_end {
        my $self  = shift;
        my $event = shift;

        $self->write(output => "\n");
        return;
    }

    # Print a plus for passes, minus for failures.
    sub handle_result {
        my $self   = shift;
        my $result = shift;

        my $out = $result->is_fail ? "-" : "+";
        $self->write(output => $out);

        return;
    }

    1;

=cut
209
2101;