use AMQPEnvelope;
use Eloquent\Liberator\Liberator;
use Kastilyo\RabbitHole\Subscriber\SubscriberInterface;
use Kastilyo\RabbitHole\Subscriber\SubscriberTrait;
use Kastilyo\RabbitHole\Exceptions\ImplementationException;
use Kastilyo\RabbitHole\AMQP\QueueBuilder;
use Kastilyo\RabbitHole\AMQP\ExchangeBuilder;
describe('BatchSubscriber', function () {
    beforeEach(function () {
        $this->amqp_connection = Helper::getAMQPConnection();
        $this->batch_subscriber = new BatchSubscriber($this->amqp_connection);
    });
    describe('->processMessage', function () {
        beforeEach(function () {
            $this->envelopes = array_map(function ($ignore) {
                $envelope = Helper::getAMQPEnvelope();
                Stub::on($envelope)->method('getDeliveryTag')->andReturn('some_delivery_tag');
                return $envelope;
            }, array_fill(0, $this->batch_subscriber->getBatchCount(), null));
            Stub::on($this->batch_subscriber)->method('acknowledgeMessage');
            // process three ahead of time
            $this->batch_subscriber->processMessage($this->envelopes[0]);
            $this->batch_subscriber->processMessage($this->envelopes[1]);
            $this->batch_subscriber->processMessage($this->envelopes[2]);
        });
        it("doesn't acknowledge messages if the limit hasn't been reached", function () {
            array_map(function ($envelope) {
                expect($this->batch_subscriber)->not->toReceive('acknowledgeMessage')->with($envelope);
            }, $this->envelopes);
            $this->batch_subscriber->processMessage($this->envelopes[3]);
        });
<?php

namespace Kastilyo\RabbitHole\Spec;

use kahlan\plugin\Stub;
use kahlan\Arg;
use Kastilyo\RabbitHole\Exceptions\InvalidPropertyException;
use Kastilyo\RabbitHole\AMQP\QueueBuilder;
describe('QueueBuilder', function () {
    beforeEach(function () {
        Helper::initializeAMQPStubs();
        $this->connection = Helper::getAMQPConnection();
        $this->channel = Helper::getAMQPChannel();
        Stub::on('AMQPQueue')->method('getChannel')->andReturn($this->channel);
        $this->queue_builder = new QueueBuilder($this->connection);
    });
    describe('->get', function () {
        beforeEach(function () {
            $this->queue_name = 'some_queue_name';
            $this->exchange_name = 'some_exchange_name';
            $this->binding_keys = ['some_binding_key', 'another_binding_key'];
            $this->queue_builder->setName($this->queue_name)->setExchangeName($this->exchange_name)->setBindingKeys($this->binding_keys);
        });
        it("makes the connection if it hasn't been made yet", function () {
            expect($this->connection)->toReceive('connect');
            $this->queue_builder->get();
        });
        it("doesn't make the connection if it's been made already", function () {
            Stub::on($this->connection)->method('isConnected')->andReturn(true);
            expect($this->connection)->not->toReceive('connect');
            $this->queue_builder->get();
<?php

namespace Kastilyo\RabbitHole\Spec;

use kahlan\plugin\Stub;
use kahlan\Arg;
use Kastilyo\RabbitHole\Exceptions\InvalidPropertyException;
use Kastilyo\RabbitHole\AMQP\ExchangeBuilder;
describe('ExchangeBuilder', function () {
    beforeEach(function () {
        Helper::initializeAMQPStubs();
        $this->connection = Helper::getAMQPConnection();
        $this->exchange_builder = new ExchangeBuilder($this->connection);
    });
    context('->get', function () {
        beforeEach(function () {
            $this->exchange_name = 'some_exchange';
            $this->exchange_builder->setName($this->exchange_name);
        });
        it("makes the connection if it hasn't been made yet", function () {
            expect($this->connection)->toReceive('connect');
            $this->exchange_builder->get();
        });
        it("doesn't make the connection if it's been made already", function () {
            Stub::on($this->connection)->method('isConnected')->andReturn(true);
            expect($this->connection)->not->toReceive('connect');
            $this->exchange_builder->get();
        });
        context('Exchange declaration', function () {
            it('sets the name of the exchange', function () {
                expect('AMQPExchange')->toReceive('setName')->with($this->exchange_name);
                Stub::on($this->subscriber)->method('getBindingKeys');
                $this->expectImplementationException();
            });
            it('throws an exception when batch count is an empty value', function () {
                Stub::on($this->subscriber)->method('getBatchCount');
                $this->expectImplementationException();
            });
            it('throws an exception when batch count is non-integer value', function () {
                Stub::on($this->subscriber)->method('getBatchCount', function () {
                    return 'asdf';
                });
                $this->expectImplementationException();
            });
        });
        it('sets processMessage as the callback', function () {
            expect($this->amqp_queue_spy)->toReceive('consume')->with([$this->subscriber, 'processMessage']);
            $this->subscriber->consume();
        });
    });
    describe('->acknowledgeMessage', function () {
        it("calls ack on the queue, passing in the message's delivery tag", function () {
            $expected_delivery_tag = 'some_delivery_tag';
            $message_spy = Helper::getAMQPEnvelope();
            Stub::on($message_spy)->method('getDeliveryTag')->andReturn($expected_delivery_tag);
            Stub::on($this->amqp_queue_spy)->method('ack', function ($delivery_tag, $flags = AMQP_NOPARAM) {
            });
            expect($this->amqp_queue_spy)->toReceive('ack')->with($expected_delivery_tag, Arg::toBeAny());
            $this->subscriber->acknowledgeMessage($message_spy);
        });
    });
});