The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl

use strict;
use warnings;

use Test::More;
use Test::Moose;

use Bread::Board::ConstructorInjection;
use Bread::Board::LifeCycle::Singleton;
use Bread::Board::Literal;

{
    package Needle;
    use Moose;

    package Mexican::Black::Tar;
    use Moose;

    package Addict;
    use Moose;

    has 'needle' => (is => 'ro');
    has 'spoon'  => (is => 'ro');
    has 'stash'  => (is => 'ro');
}

my $s = Bread::Board::ConstructorInjection->new(
    lifecycle    => 'Singleton',
    name         => 'William',
    class        => 'Addict',
    dependencies => {
        needle => Bread::Board::ConstructorInjection->new(name => 'spike', class => 'Needle'),
        spoon  => Bread::Board::Literal->new(name => 'works', value => 'Spoon!'),
    },
    parameters => {
        stash => { isa => 'Mexican::Black::Tar' }
    }
);
isa_ok($s, 'Bread::Board::ConstructorInjection');
does_ok($s, 'Bread::Board::Service::WithClass');
does_ok($s, 'Bread::Board::Service::WithDependencies');
does_ok($s, 'Bread::Board::Service::WithParameters');
does_ok($s, 'Bread::Board::Service');
does_ok($s, 'Bread::Board::LifeCycle::Singleton');
is($s->lifecycle, 'Singleton', '... got the right lifecycle');

ok(!$s->has_instance, '... we dont have an instance yet');

my $i = $s->get(stash => Mexican::Black::Tar->new);

ok($s->has_instance, '... we do have an instance now');

isa_ok($i, 'Addict');
isa_ok($i->needle, 'Needle');
is($i->spoon, 'Spoon!', '... got our literal service');
isa_ok($i->stash, 'Mexican::Black::Tar');

{
    my $i2 = $s->get(stash => Mexican::Black::Tar->new);
    is($i, $i2, '... calling it again returns the same object');
}

$s->flush_instance;

{
    my $i2 = $s->get(stash => Mexican::Black::Tar->new);
    isnt($i, $i2, '... calling it again returns an new object');

    {
        my $i2a = $s->get(stash => Mexican::Black::Tar->new);
        is($i2, $i2a, '... calling it again returns the same object');
    }

    $s->lifecycle('Null');
    ok(!$s->can('flush_instance'), '... we can no longer call flush_instance');
    ok(!$s->can('instance'), '... we can no longer call instance');
    ok(!$s->can('has_instance'), '... we can no longer call has_instance');

    is($s->lifecycle, 'Null', '... got the right lifecycle');

    {
        my $i2a = $s->get(stash => Mexican::Black::Tar->new);
        isnt($i2, $i2a, '... calling it again returns a new object');

        {
            my $i2a1 = $s->get(stash => Mexican::Black::Tar->new);
            isnt($i2, $i2a1, '... calling it again returns a new object as before');
            isnt($i2a, $i2a1, '... calling it again returns a new object');
        }
    }
}

$s->lifecycle('Singleton');
ok($s->can('flush_instance'), '... we can no longer call flush_instance');
ok($s->can('instance'), '... we can no longer call instance');
ok($s->can('has_instance'), '... we can no longer call has_instance');

is($s->lifecycle, 'Singleton', '... got the right lifecycle');

{
    my $i2 = $s->get(stash => Mexican::Black::Tar->new);
    isnt($i, $i2, '... calling it again returns the same object');

    {
        my $i2a = $s->get(stash => Mexican::Black::Tar->new);
        is($i2, $i2a, '... calling it again returns the same object');
    }
}

done_testing;