#!/usr/bin/perl use strict; BEGIN { $| = 1; $^W = 1; } use Test::More tests => 24; use Test::NoWarnings; use Test::Exception; use Aspect; use Aspect::Library::Listenable; # Set up the Listenable relationship types aspect Listenable => ( Erase => call "Foo::set_erased", ); aspect Listenable => ( Color => call "Foo::set_color", color => 'get_color', ); # Create a temporary lexical aspect to make sure we create lexical advice SCOPE: { my $lexical = aspect Listenable => ( Foo => call 'Baz::one', ); isa_ok( $lexical, 'Aspect::Library::Listenable' ); } ###################################################################### # Main Tests SCOPE: { my $has_been_called = 0; my $point = Foo->new; add_listener( $point, Erase => my $listener = sub { $has_been_called = 1 } ); $point->set_erased; ok( $point->get_erased, 'has been erased' ); ok( $has_been_called, 'has been called' ); remove_listener( $point, Erase => $listener ); } SCOPE: { my $has_been_called1 = 0; my $has_been_called2 = 0; my $point = Foo->new; add_listener( $point, Erase => my $listener1 = sub { $has_been_called1 = 1 } ); add_listener( $point, Erase => my $listener2 = sub { $has_been_called2 = 1 } ); $point->set_erased; ok( $has_been_called1, 'listener 1' ); ok( $has_been_called2, 'listener 2' ); remove_listener( $point, Erase => $listener1 ); remove_listener( $point, Erase => $listener2 ); } SCOPE: { my $has_been_called1 = 0; my $has_been_called2 = 0; my $point1 = Foo->new; my $point2 = Foo->new; add_listener( $point1, Erase => my $listener1 = sub { $has_been_called1 = 1 } ); add_listener( $point2, Erase => my $listener2 = sub { $has_been_called2 = 1 } ); $point2->set_erased; ok( !$point1->get_erased, 'point 1' ); ok( $point2->get_erased, 'point 2' ); ok( !$has_been_called1, 'listener 1' ); ok( $has_been_called2, 'listener 2' ); remove_listener( $point1, Erase => $listener1 ); remove_listener( $point2, Erase => $listener2 ); } SCOPE: { my $has_been_called1 = 0; my $has_been_called2 = 0; my $point = Foo->new; add_listener( $point, Erase => my $listener1 = sub { $has_been_called1 = 1 } ); add_listener( $point, Erase => my $listener2 = sub { $has_been_called2 = 1 } ); remove_listener( $point, Erase => $listener1 ); $point->set_erased; ok( !$has_been_called1, 'listener 1' ); ok( $has_been_called2, 'listener 2' ); remove_listener( $point, Erase => $listener2 ); } SCOPE: { my $event = 0; my $point = Foo->new; add_listener( $point, Color => my $listener = sub { $event = shift } ); $point->set_color('red'); is( $point->get_color, 'red', 'point color' ); ok( $event, 'event fired' ); is( ref $event, 'Aspect::Library::Listenable::Event', 'event class' ); is( $event->name, 'Color', 'name' ); is( $event->source, $point, 'source' ); is( $event->color, 'red', 'color' ); is( $event->old_color, 'blue', 'old_color' ); is_deeply( $event->params, [ 'red' ], 'args' ); remove_listener( $point, Color => $listener ); } SCOPE: { my $hasnt_been_called = 1; my $point = Foo->new; add_listener( $point, Color => my $listener = sub { $hasnt_been_called = 0 } ); $point->set_color('blue'); ok( $hasnt_been_called ); remove_listener( $point, Color => $listener ); } SCOPE: { my $listenable = bless [], 'SomePackage'; throws_ok( sub { add_listener( $listenable, Event => sub {} ) }, qr/not a hash based object/, ); } SCOPE: { my $point = Foo->new; add_listener( $point, Erase => [do_call => my $listener = Bar->new, [qw(source)], ] ); ok( !$listener->has_been_called, 'before erased' ); $point->set_erased; is( $listener->has_been_called, $point, 'after erased' ); remove_listener( $point, Erase => $listener ); } ###################################################################### # Support Classes package Foo; sub new { bless { color => 'blue', erased => 0, }, shift; } sub get_erased { shift->{erased} } sub set_erased { shift->{erased} = 1; } sub get_color { shift->{color}; } sub set_color { shift->{color} = pop; } package Bar; sub new { bless { has_been_called => 0, }, shift; } sub do_call { shift->{has_been_called} = pop; } sub has_been_called { shift->{has_been_called}; } package Baz; sub one { return 'one'; }