From 25158322162000dc0e070028985c29410246fc11 Mon Sep 17 00:00:00 2001
From: Tobias Nyholm <tobias.nyholm@gmail.com>
Date: Fri, 5 Aug 2016 10:40:49 +0200
Subject: [PATCH] Added functional tests

---
 .../Tests/Functional/MockedMailgun.php        | 85 +++++++++++++++++++
 .../Tests/Functional/MockedRestClient.php     | 84 ++++++++++++++++++
 .../Tests/Functional/SendMessageTest.php      | 31 +++++++
 3 files changed, 200 insertions(+)
 create mode 100644 tests/Mailgun/Tests/Functional/MockedMailgun.php
 create mode 100644 tests/Mailgun/Tests/Functional/MockedRestClient.php
 create mode 100644 tests/Mailgun/Tests/Functional/SendMessageTest.php

diff --git a/tests/Mailgun/Tests/Functional/MockedMailgun.php b/tests/Mailgun/Tests/Functional/MockedMailgun.php
new file mode 100644
index 0000000..1310218
--- /dev/null
+++ b/tests/Mailgun/Tests/Functional/MockedMailgun.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace Mailgun\Tests\Functional;
+
+use Mailgun\Mailgun;
+
+/**
+ * A client to be used in tests.
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+final class MockedMailgun extends Mailgun
+{
+    /**
+     * @param MockedRestClient $restClient
+     *
+     * @internal Use MockedMailgun::create()
+     */
+    public function __construct(MockedRestClient $restClient)
+    {
+        $this->apiKey = 'apikey';
+        $this->restClient = $restClient;
+    }
+
+    public function getMockedRestClient()
+    {
+        return $this->restClient;
+    }
+
+    /**
+     * Create a mocked mailgun client with a mocked RestClient.
+     *
+     * @param \PHPUnit_Framework_TestCase $testCase
+     * @param \Closure|string             $methodValidator
+     * @param \Closure|string             $uriValidator
+     * @param \Closure|mixed              $bodyValidator
+     * @param \Closure|array              $filesValidator
+     * @param \Closure|array              $headersValidator
+     */
+    public static function create(
+        \PHPUnit_Framework_TestCase $testCase,
+        $methodValidator,
+        $uriValidator,
+        $bodyValidator = null,
+        $filesValidator = [],
+        $headersValidator = []
+    ) {
+        if (!$methodValidator instanceof \Closure) {
+            $methodValidator = self::createClosure($testCase, $methodValidator);
+        }
+
+        if (!$uriValidator instanceof \Closure) {
+            $uriValidator = self::createClosure($testCase, $uriValidator);
+        }
+
+        if (!$bodyValidator instanceof \Closure) {
+            $bodyValidator = self::createClosure($testCase, $bodyValidator);
+        }
+
+        if (!$filesValidator instanceof \Closure) {
+            $filesValidator = self::createClosure($testCase, $filesValidator);
+        }
+
+        if (!$headersValidator instanceof \Closure) {
+            $headersValidator = self::createClosure($testCase, $headersValidator);
+        }
+
+        return new self(new MockedRestClient($methodValidator, $uriValidator, $bodyValidator, $filesValidator, $headersValidator));
+    }
+
+    /**
+     * Return a closure.
+     *
+     * @param \PHPUnit_Framework_TestCase $testCase
+     * @param $expectedValue
+     *
+     * @return \Closure
+     */
+    private static function createClosure(\PHPUnit_Framework_TestCase $testCase, $expectedValue)
+    {
+        return function ($value) use ($testCase, $expectedValue) {
+            $testCase->assertEquals($expectedValue, $value);
+        };
+    }
+}
diff --git a/tests/Mailgun/Tests/Functional/MockedRestClient.php b/tests/Mailgun/Tests/Functional/MockedRestClient.php
new file mode 100644
index 0000000..571fc91
--- /dev/null
+++ b/tests/Mailgun/Tests/Functional/MockedRestClient.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace Mailgun\Tests\Functional;
+
+use Mailgun\Connection\RestClient;
+
+/**
+ * A rest client that validate arguments to the send method.
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ *
+ * @internal
+ */
+final class MockedRestClient extends RestClient
+{
+    /**
+     * @var \Closure
+     */
+    private $methodValidator;
+
+    /**
+     * @var \Closure
+     */
+    private $uriValidator;
+
+    /**
+     * @var \Closure
+     */
+    private $bodyValidator;
+
+    /**
+     * @var \Closure
+     */
+    private $filesValidator;
+
+    /**
+     * @var \Closure
+     */
+    private $headersValidator;
+
+    /**
+     * @param \Closure $methodValidator
+     * @param \Closure $uriValidator
+     * @param \Closure $bodyValidator
+     * @param \Closure $filesValidator
+     * @param \Closure $headersValidator
+     *
+     * @internal Do not use this constructor. Use MockedMailgun::create()
+     */
+    public function __construct(
+        \Closure $methodValidator,
+        \Closure $uriValidator,
+        \Closure $bodyValidator,
+        \Closure $filesValidator,
+        \Closure $headersValidator
+    ) {
+        $this->methodValidator = $methodValidator;
+        $this->uriValidator = $uriValidator;
+        $this->bodyValidator = $bodyValidator;
+        $this->filesValidator = $filesValidator;
+        $this->headersValidator = $headersValidator;
+    }
+
+    /**
+     * Override the send function and validate the parameters.
+     */
+    protected function send($method, $uri, $body = null, $files = [], array $headers = [])
+    {
+        $f = $this->methodValidator;
+        $f($method);
+
+        $f = $this->uriValidator;
+        $f($uri);
+
+        $f = $this->bodyValidator;
+        $f($body);
+
+        $f = $this->filesValidator;
+        $f($files);
+
+        $f = $this->headersValidator;
+        $f($headers);
+    }
+}
diff --git a/tests/Mailgun/Tests/Functional/SendMessageTest.php b/tests/Mailgun/Tests/Functional/SendMessageTest.php
new file mode 100644
index 0000000..193a2bf
--- /dev/null
+++ b/tests/Mailgun/Tests/Functional/SendMessageTest.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Mailgun\Tests\Functional;
+
+/**
+ * Simple test to show how to use the MockedMailgun client
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+class SendMessageTest extends \PHPUnit_Framework_TestCase
+{
+    public function testSimpleExample()
+    {
+        // Create a Closure that validates the $files parameter to RestClient::send()
+        $fileValidator = function($files) {
+            $this->assertContains(['name'=>'from',    'contents'=>'bob@example.com'], $files);
+            $this->assertContains(['name'=>'to',      'contents'=>'alice@example.com'], $files);
+            $this->assertContains(['name'=>'subject', 'contents'=>'Foo'], $files);
+            $this->assertContains(['name'=>'text',    'contents'=>'Bar'], $files);
+        };
+
+        // Create the mocked mailgun client. We use $this->assertEquals on $method, $uri and $body parameters.
+        $mailgun = MockedMailgun::create($this, 'POST', 'domain/messages', [], $fileValidator);
+
+        $mailgun->sendMessage('domain', array(
+            'from'    => 'bob@example.com',
+            'to'      => 'alice@example.com',
+            'subject' => 'Foo',
+            'text'    => 'Bar'));
+        }
+}