diff --git a/composer.json b/composer.json index 7e49ab7..43cfc8c 100644 --- a/composer.json +++ b/composer.json @@ -4,13 +4,18 @@ "homepage": "https://github.com/DripEmail/drip-php", "license": "MIT", "autoload": { - "psr-4": { "Drip\\": "src" } + "psr-4": { + "Drip\\": "src", + "DripTests\\": "tests" + } }, "require-dev": { "phpunit/phpunit": "^5", "squizlabs/php_codesniffer": "3.*" }, "require": { - "guzzlehttp/guzzle": "^6.3" + "guzzlehttp/guzzle": "^6.3", + "respect/validation": "^1.1", + "ext-json": "^1" } } diff --git a/phpunit.xml b/phpunit.xml index 93c7295..36ec8e4 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -3,6 +3,7 @@ api_end_point = $options['api_end_point']; - } - // NOTE: For testing. Could break at any time, please do not depend on this. - if (\array_key_exists('guzzle_stack_constructor', $options)) { - $this->guzzle_stack_constructor = $options['guzzle_stack_constructor']; - } - // TODO: allow setting timeouts - - $api_token = trim($api_token); - if (empty($api_token) || !preg_match('#^[\w-]+$#si', $api_token)) { - throw new InvalidApiTokenException("Missing or invalid Drip API token."); - } - $this->api_token = $api_token; - - - $account_id = trim($account_id); - if (empty($account_id) || !preg_match('#^[\w-]+$#si', $account_id)) { - throw new InvalidAccountIdException("Missing or invalid Drip API token."); - } - $this->account_id = $account_id; - } - - /** - * Requests the campaigns for the given account. - * @param array $params Set of arguments - * - status (optional) - * @return \Drip\ResponseInterface - */ - public function get_campaigns($params) - { - if (isset($params['status'])) { - if (!in_array($params['status'], array('active', 'draft', 'paused', 'all'))) { - throw new InvalidArgumentException("Invalid campaign status."); - } - } - - return $this->make_request("$this->account_id/campaigns", $params); - } - - /** - * Fetch a campaign for the given account based on it's ID. - * @param array $params Set of arguments - * - campaign_id (required) - * @return \Drip\ResponseInterface - */ - public function fetch_campaign($params) - { - if (empty($params['campaign_id'])) { - throw new InvalidArgumentException("campaign_id was not specified"); - } - - $campaign_id = $params['campaign_id']; - unset($params['campaign_id']); // clear it from the params - - return $this->make_request("$this->account_id/campaigns/$campaign_id", $params); - } - - /** - * Requests the accounts for the given account. - * Parses the response JSON and returns an array which contains: id, name, created_at etc - * @param void - * @return \Drip\ResponseInterface - */ - public function get_accounts() - { - return $this->make_request('accounts'); - } - - /** - * Sends a request to add a subscriber and returns its record or false - * + * @param v $validator * @param array $params - * @return \Drip\ResponseInterface - */ - public function create_or_update_subscriber($params) - { - // The API wants the params to be JSON encoded - return $this->make_request( - "$this->account_id/subscribers", - array('subscribers' => array($params)), - self::POST - ); - } - - /** - * Sends a request to add/update a batch (up to 1000) of subscribers - * - * @param array $params - * @return \Drip\ResponseInterface - */ - public function create_or_update_subscribers($params) - { - return $this->make_request( - "$this->account_id/subscribers/batches", - $params, - self::POST - ); - } - - /** - * Returns info regarding a particular subscriber - * - * @param array $params - * @return \Drip\ResponseInterface + * @throws InvalidArgumentException */ - public function fetch_subscriber($params) + protected static function validate_params($validator, $params) { - if (!empty($params['subscriber_id'])) { - $subscriber_id = $params['subscriber_id']; - unset($params['subscriber_id']); // clear it from the params - } else if (!empty($params['email'])) { - $subscriber_id = $params['email']; - unset($params['email']); // clear it from the params - } else { - throw new InvalidArgumentException("Subscriber ID or Email was not specified. You must specify either Subscriber ID or Email."); + try { + $validator->assert($params); + } catch (ValidationException $e) { + throw new InvalidArgumentException($e->getFullMessage()); } - - $subscriber_id = urlencode($subscriber_id); - - return $this->make_request("$this->account_id/subscribers/$subscriber_id"); } /** - * Returns a list of subscribers - * - * @return \Drip\ResponseInterface - */ - public function fetch_subscribers() - { - - return $this->make_request("$this->account_id/subscribers"); - } - - /** - * Subscribes a user to a given campaign for a given account. - * - * @param array $params + * @param string $api_token + * @param string $account_id + * @param string $api_end_point + * @param callable $guzzle_stack_constructor + * @param int $timeout + * @param int $connect_timeout + * @throws InvalidApiTokenException|InvalidAccountIdException */ - public function subscribe_subscriber($params) + public static function init_client($api_token = null, $account_id = null, $api_end_point = 'https://api.getdrip.com/v2/', $guzzle_stack_constructor = null, $timeout = 30, $connect_timeout = 30) { - if (empty($params['campaign_id'])) { - throw new InvalidArgumentException("Campaign ID not specified"); + if ($api_token === null) { + $api_token = getenv('DRIP_API_TOKEN'); } - $campaign_id = $params['campaign_id']; - unset($params['campaign_id']); // clear it from the params - - if (empty($params['email'])) { - throw new InvalidArgumentException("Email not specified"); + if (empty($api_token) || !preg_match('#^[\w-]+$#si', $api_token)) { + throw new InvalidApiTokenException("Missing or invalid Drip API token."); } - if (!isset($params['double_optin'])) { - $params['double_optin'] = true; + if ($account_id === null) { + $account_id = getenv('DRIP_ACCOUNT_ID'); } - // The API wants the params to be JSON encoded - $req_params = array('subscribers' => array($params)); - - return $this->make_request("$this->account_id/campaigns/$campaign_id/subscribers", $req_params, self::POST); - } - - /** - * - * Some keys are removed from the params so they don't get send with the other data to Drip. - * - * @param array $params - */ - public function unsubscribe_subscriber($params) - { - if (!empty($params['subscriber_id'])) { - $subscriber_id = $params['subscriber_id']; - unset($params['subscriber_id']); // clear it from the params - } else if (!empty($params['email'])) { - $subscriber_id = $params['email']; - unset($params['email']); // clear it from the params - } else { - throw new InvalidArgumentException("Subscriber ID or Email was not specified. You must specify either Subscriber ID or Email."); + if (empty($account_id) || !preg_match('#^[\w-]+$#si', $account_id)) { + throw new InvalidAccountIdException("Missing or invalid Drip API token."); } - $subscriber_id = urlencode($subscriber_id); - return $this->make_request("$this->account_id/subscribers/$subscriber_id/unsubscribe", $params, self::POST); + self::$api_token = $api_token; + self::$account_id = $account_id; + self::$api_end_point = $api_end_point; + self::$guzzle_stack_constructor = $guzzle_stack_constructor; + self::$timeout = $timeout; + self::$connect_timeout = $connect_timeout; + self::$initialised = true; } - /** - * - * This calls POST /:account_id/tags to add the tag. It just returns some status code no content - * - * @param array $params - * @param bool $status - */ - public function tag_subscriber($params) + public static function is_initialized() { - if (empty($params['email'])) { - throw new InvalidArgumentException("Email was not specified"); - } - - if (empty($params['tag'])) { - throw new InvalidArgumentException("Tag was not specified"); - } - - // The API wants the params to be JSON encoded - $req_params = array('tags' => array($params)); - - return $this->make_request("$this->account_id/tags", $req_params, self::POST); + return self::$initialised; } /** * - * This calls DELETE /:account_id/tags to remove the tags. It just returns some status code no content - * + * @param string $url * @param array $params - * @param bool $status success or failure + * @param $req_method + * @param v $validator + * @param $endpoint_version + * @return \Drip\ResponseInterface + * @throws InvalidArgumentException|UnexpectedHttpVerbException|GuzzleException|UnitializedException */ - public function untag_subscriber($params) + protected static function make_request($url, $params = array(), $req_method = DripAPIInterface::GET, $validator = null, $endpoint_version = 2) { - if (empty($params['email'])) { - throw new InvalidArgumentException("Email was not specified"); - } - - if (empty($params['tag'])) { - throw new InvalidArgumentException("Tag was not specified"); + // Check if we have initialized all the variables + if (!self::is_initialized()) { + try { + self::init_client(); //try to initialise the client + } catch (\Exception $e) { + throw new UnitializedException("Drip Client not initialized properly"); + } + if (!self::is_initialized()) { // still not initialised + throw new UnitializedException("Drip Client not initialized properly"); + } } - // The API wants the params to be JSON encoded - $req_params = array('tags' => array($params)); - - return $this->make_request("$this->account_id/tags", $req_params, self::DELETE); - } - /** - * - * Posts an event specified by the user. - * - * @param array $params - * @param bool - */ - public function record_event($params) - { - if (empty($params['action'])) { - throw new InvalidArgumentException("Action was not specified"); + if ($validator === null) { + $validator = v::alwaysValid(); } - // The API wants the params to be JSON encoded - $req_params = array('events' => array($params)); + self::validate_params($validator, $params); - return $this->make_request("$this->account_id/events", $req_params, self::POST); - } - - /** - * @return string - */ - protected function user_agent() - { - return "Drip API PHP Wrapper (getdrip.com). Version " . self::VERSION; - } - - /** - * Determines whether the response is a success. - * - * @param int $code - * @return boolean - */ - protected function is_success_response($code) - { - return $code >= 200 && $code <= 299; - } - - /** - * - * @param string $url - * @param array $params - * @param int $req_method - * @return \Drip\ResponseInterface - * @throws Exception - */ - protected function make_request($url, $params = array(), $req_method = self::GET) - { - if ($this->guzzle_stack_constructor) { + if (self::$guzzle_stack_constructor) { // This can be replaced with `($this->guzzle_stack_constructor)()` once we drop PHP5 support. - $fn = $this->guzzle_stack_constructor; + $fn = self::$guzzle_stack_constructor; $stack = $fn(); } else { // @codeCoverageIgnoreStart $stack = \GuzzleHttp\HandlerStack::create(); // @codeCoverageIgnoreEnd } + + $endpoint = $endpoint_version == 2 ? self::$api_end_point : 'https://api.getdrip.com/v3/'; + $client = new \GuzzleHttp\Client([ - 'base_uri' => $this->api_end_point, + 'base_uri' => $endpoint, 'handler' => $stack, ]); $req_params = [ - 'auth' => [$this->api_token, ''], - 'timeout' => $this->timeout, - 'connect_timeout' => $this->connect_timeout, + 'auth' => [self::$api_token, ''], + 'timeout' => self::$timeout, + 'connect_timeout' => self::$connect_timeout, 'headers' => [ - 'User-Agent' => $this->user_agent(), + 'User-Agent' => self::user_agent(), 'Accept' => 'application/json, text/javascript, */*; q=0.01', 'Content-Type' => 'application/vnd.api+json', ], @@ -352,26 +164,71 @@ protected function make_request($url, $params = array(), $req_method = self::GET ]; switch ($req_method) { - case self::GET: + case DripAPIInterface::GET: $req_params['query'] = $params; break; - case self::POST: - case self::DELETE: - // @codeCoverageIgnoreStart - case self::PUT: - // @codeCoverageIgnoreEnd + case DripAPIInterface::POST: + case DripAPIInterface::DELETE: + // @codeCoverageIgnoreStart + case DripAPIInterface::PUT: + // @codeCoverageIgnoreEnd $req_params['body'] = is_array($params) ? json_encode($params) : $params; break; default: // @codeCoverageIgnoreStart throw new UnexpectedHttpVerbException("Unexpected HTTP verb $req_method"); break; - // @codeCoverageIgnoreEnd + // @codeCoverageIgnoreEnd } $res = $client->request($req_method, $url, $req_params); - $success_klass = $this->is_success_response($res->getStatusCode()) ? \Drip\SuccessResponse::class : \Drip\ErrorResponse::class; + $success_klass = self::is_success_response($res->getStatusCode()) ? SuccessResponse::class : ErrorResponse::class; return new $success_klass($url, $params, $res); } + + /** + * @return string + */ + protected static function user_agent() + { + return "Drip API PHP Wrapper (getdrip.com). Version " . DripAPIInterface::VERSION; + } + + /** + * Determines whether the response is a success. + * + * @param int $code + * @return boolean + */ + protected static function is_success_response($code) + { + return $code >= 200 && $code <= 299; + } + + + /** + * Accepts the token and saves it internally. + * + * @param string $api_token e.g. qsor48ughrjufyu2dadraasfa1212424 + * @param string $account_id e.g. 123456 + * @param array $options + * * `api_end_point` (mostly for Drip internal testing) + * * `guzzle_stack_constructor` (for test suite, may break at any time, do not use) + * @throws Exception + */ + public function __construct($api_token, $account_id, $options = []) + { + $api_token = trim($api_token); + $account_id = trim($account_id); + self::init_client($api_token, $account_id); + if (\array_key_exists('api_end_point', $options)) { + self::$api_end_point = $options['api_end_point']; + } + // NOTE: For testing. Could break at any time, please do not depend on this. + if (\array_key_exists('guzzle_stack_constructor', $options)) { + self::$guzzle_stack_constructor = $options['guzzle_stack_constructor']; + } + // TODO: allow setting timeouts + } } diff --git a/src/DripAPIInterface.php b/src/DripAPIInterface.php new file mode 100644 index 0000000..521574b --- /dev/null +++ b/src/DripAPIInterface.php @@ -0,0 +1,11 @@ +positive(), false), + v::key('sort', v::in(array('id', 'created_at')), false), + v::key('direction', v::in(array('asc', 'desc')), false), + v::key('per_page', v::intType()->between(1, 1000), false) + ); + + return self::make_request(self::$account_id . "/campaigns/$campaign_id/subscribers", $params, self::GET, $v); + } +} diff --git a/src/Resources/Conversion.php b/src/Resources/Conversion.php new file mode 100644 index 0000000..98e241a --- /dev/null +++ b/src/Resources/Conversion.php @@ -0,0 +1,43 @@ +key('per_page', v::intVal()->between(1, 1000), false); + + return self::make_request(self::$account_id . "/event_actions", $params, self::GET, $v); + } + + /** + * + * Posts an event specified by the user. + * + * @param array $params + * @return ResponseInterface + * @throws InvalidArgumentException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public static function record_event($params) + { + $v = v::keyNested('events.0.action', v::stringType(), true) + ->keyNested('events.0.prospect', v::boolType(), false) + ->keyNested('events.0.properties', v::arrayType(), false) + ->keyNested('events.0.occurred_at', v::date(\DateTime::ISO8601), false) + ->oneOf( + v::keyNested('events.0.email'), + v::keyNested('events.0.id') + ); + + // The API wants the params to be JSON encoded + $req_params = array('events' => array($params)); + + return self::make_request(self::$account_id . "/events", $req_params, self::POST, $v); + } +} diff --git a/src/Resources/Form.php b/src/Resources/Form.php new file mode 100644 index 0000000..94c096b --- /dev/null +++ b/src/Resources/Form.php @@ -0,0 +1,34 @@ +each(V::allOf( + v::key('product_id', null, false), + v::key('product_variant_id', null, false), + v::key('sku', null, false), + v::key('name', V::stringType(), true), + v::key('brand', V::stringType(), false), + v::key('categories', V::arrayType(), false), + v::key('price', V::floatType(), true), + v::key('quantity', V::intType(), false), + v::key('discounts', V::floatType(), false), + v::key('taxes', V::floatType(), false), + v::key('fees', V::floatType(), false), + v::key('shipping', V::floatType(), false), + v::key('total', V::floatType(), false), + v::key('product_url', V::stringType(), false), + v::key('image_url', V::stringType(), false) + )); + + return ( + v::oneOf( + v::key('email'), + v::key('person_id') + )->AllOf( + v::key('provider', v::stringType(), true), + v::key('action', V::in(['placed', 'updated', 'paid', 'fulfilled', 'refunded', 'canceled']), true), + v::key('occurred_at', V::date(\DateTime::ISO8601), false), + v::key('new_email', v::email(), false), + v::key('order_id', v::stringType(), true), + v::key('order_public_id', v::stringType(), false), + v::key('grand_total', v::floatType(), false), + v::key('total_discounts', v::floatType(), false), + v::key('total_taxes', v::floatType(), false), + v::key('total_fees', v::floatType(), false), + v::key('total_shipping', v::floatType(), false), + v::key('refund_amount', v::floatType(), false), + v::key('currency', V::currencyCode(), false), + v::key('order_url', V::stringType(), false), + v::key('items', $itemsValidator, true), + v::key('billing_address', $addressValidator, false), + v::key('shipping_address', $addressValidator, false) + )); + } + + public static function create_order_activity_events($orders) + { + $orderBatches = array_chunk($orders, 1000, true); + foreach ($orderBatches as $orderBatch) { + foreach ($orderBatch as $order) { + try { + self::get_order_validator()->assert($order); + } catch (ValidationException $e) { + throw new InvalidArgumentException($e->getFullMessage()); + } + } + + $p = ['orders' => $orderBatch]; + + $result = self::make_request(self::$account_id . "/shopper_activity/order/batch", $p, self::POST, null, 3); + if ($result instanceof ErrorResponse) { + return $result; + } + } + + return $result; //Assume success; + } +} diff --git a/src/Resources/Subscriber.php b/src/Resources/Subscriber.php new file mode 100644 index 0000000..af3e24d --- /dev/null +++ b/src/Resources/Subscriber.php @@ -0,0 +1,228 @@ +AllOf( + v::key('email', v::email(), false), + v::key('id', null, false), + v::key('visitor_uuid', null, false), + v::key('new_email', v::email(), false), + v::key('first_name', v::stringType(), false), + v::key('last_name', v::stringType(), false), + v::key('address1', v::stringType(), false), + v::key('address2', v::stringType(), false), + v::key('city', v::stringType(), false), + v::key('state', v::stringType(), false), + v::key('zip', v::stringType(), false), + v::key('country', v::stringType(), false), + v::key('phone', null, false), + v::key('user_id', null, false), + v::key('time_zone', v::stringType(), false), + v::key('lifetime_value', v::numeric(), false), + v::key('ip_address', v::ip(), false), + v::key('custom_fields', v::objectType(), false), + v::key('tags', v::arrayType(), false), + v::key('remove_tags', v::arrayType(), false), + v::key('prospect', v::boolType(), false), + v::key('base_lead_score', v::intType(), false), + v::key('eu_consent', v::in(['granted', 'denied']), false), + v::key('eu_consent_message', v::stringType(), false), + v::key('status', v::in(['active', 'unsubscribed']), false) + )->assert($subscriber); + } catch (ValidationException $e) { + throw new InvalidArgumentException($e->getFullMessage()); + }//end try + } + + /** + * Sends a request to add a subscriber and returns its record or false + * + * @param array $params + * @return \Drip\ResponseInterface + * @throws \GuzzleHttp\Exception\GuzzleException|InvalidArgumentException + */ + public static function create_or_update_subscriber($params) + { + self::validate_subscriber($params); + + // The API wants the params to be JSON encoded + return self::make_request( + self::$account_id."/subscribers", + array('subscribers' => array($params)), + self::POST + ); + } + + /** + * @param array $subscribers + * @return \Drip\ResponseInterface + * @throws \GuzzleHttp\Exception\GuzzleException|InvalidArgumentException + */ + public static function batch_create_or_update_subscribers($subscribers) + { + $subscribersBatches = array_chunk($subscribers, 1000, true); + foreach ($subscribersBatches as $subscribersBatch) { + foreach ($subscribersBatch as $subscriber) { + self::validate_subscriber($subscriber); + } + + $p = ['batches' => [['subscribers' => $subscribersBatch]]]; + + $result = self::make_request(self::$account_id."/subscribers/batches", $p, self::POST); + if ($result instanceof ErrorResponse) { + return $result; + } + } + + return $result; //Assume success; + } + + /** + * Sends a request to add/update a batch (up to 1000) of subscribers + * + * @param array $params + * @return \Drip\ResponseInterface + */ + public static function create_or_update_subscribers($params) + { + return self::make_request( + self::$account_id."/subscribers/batches", + $params, + self::POST + ); + } + + /** + * Returns info regarding a particular subscriber + * + * @param array $params + * @return \Drip\ResponseInterface + * @throws InvalidArgumentException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public static function fetch_subscriber($params) + { + if (!empty($params['subscriber_id'])) { + $subscriber_id = $params['subscriber_id']; + unset($params['subscriber_id']); // clear it from the params + } else if (!empty($params['email'])) { + $subscriber_id = $params['email']; + unset($params['email']); // clear it from the params + } else { + throw new InvalidArgumentException("Subscriber ID or Email was not specified. You must specify either Subscriber ID or Email."); + } + + $subscriber_id = urlencode($subscriber_id); + + return self::make_request(self::$account_id."/subscribers/$subscriber_id"); + } + + /** + * Returns a list of subscribers + * + * @return \Drip\ResponseInterface + */ + public static function fetch_subscribers() + { + + return self::make_request(self::$account_id."/subscribers"); + } + + /** + * Returns a list of subscribers (alias) + * + * @return \Drip\ResponseInterface + */ + public static function get_subscribers() + { + + return self::fetch_subscribers(); + } + + /** + * Subscribes a user to a given campaign for a given account. + * + * @param array $params + * @return ResponseInterface + * @throws InvalidArgumentException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public static function subscribe_subscriber($params) + { + if (empty($params['campaign_id'])) { + throw new InvalidArgumentException("Campaign ID not specified"); + } + + $campaign_id = $params['campaign_id']; + unset($params['campaign_id']); // clear it from the params + + if (empty($params['email'])) { + throw new InvalidArgumentException("Email not specified"); + } + + if (!isset($params['double_optin'])) { + $params['double_optin'] = true; + } + + // The API wants the params to be JSON encoded + $req_params = array('subscribers' => array($params)); + + return self::make_request(self::$account_id."/campaigns/$campaign_id/subscribers", $req_params, self::POST); + } + + + /** + * @param array|mixed $subscriber_id + * @return mixed + */ + public static function campaign_subscriptions($subscriber_id) + { + list($subscriber_id, $params) = self::unwrapParam($subscriber_id, 'subscriber_id'); + $subscriber_id = urlencode($subscriber_id); + return self::make_request(self::$account_id."/subscribers/$subscriber_id/campaign_subscriptions"); + } + + /** + * + * Some keys are removed from the params so they don't get send with the other data to Drip. + * + * @param array $params + * @return ResponseInterface + * @throws InvalidArgumentException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public static function unsubscribe_subscriber($params) + { + if (!empty($params['subscriber_id'])) { + $subscriber_id = $params['subscriber_id']; + unset($params['subscriber_id']); // clear it from the params + } else if (!empty($params['email'])) { + $subscriber_id = $params['email']; + unset($params['email']); // clear it from the params + } else { + throw new InvalidArgumentException("Subscriber ID or Email was not specified. You must specify either Subscriber ID or Email."); + } + + $subscriber_id = urlencode($subscriber_id); + return self::make_request(self::$account_id."/subscribers/$subscriber_id/unsubscribe", $params, self::POST); + } +} diff --git a/src/Resources/Tag.php b/src/Resources/Tag.php new file mode 100644 index 0000000..02f26b8 --- /dev/null +++ b/src/Resources/Tag.php @@ -0,0 +1,71 @@ + array($params)); + + return self::make_request(self::$account_id . "/tags", $req_params, self::POST, $v); + } + + /** + * + * This calls DELETE /:account_id/tags to remove the tags. It just returns some status code no content + * + * @param array $params + * @return ResponseInterface + * @throws InvalidArgumentException + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public static function untag_subscriber($params) + { + $v = v::keyNested( + 'tags.0', + v::keySet( + v::key('email', v::stringType(), true), + v::key('tag', v::stringType(), true) + ) + ); + + // The API wants the params to be JSON encoded + $req_params = array('tags' => array($params)); + + return self::make_request(self::$account_id . "/tags", $req_params, self::DELETE, $v); + } +} diff --git a/src/Resources/User.php b/src/Resources/User.php new file mode 100644 index 0000000..af6b00e --- /dev/null +++ b/src/Resources/User.php @@ -0,0 +1,19 @@ +assert($param); + $unwrappedParam = $param[$paramName]; + unset($param[$paramName]); // clear it from the params + } else { + $unwrappedParam = $param; + $param = []; + } + return [$unwrappedParam, $param]; + } catch (ValidationException $e) { + throw new InvalidArgumentException($e->getFullMessage()); + } + } +} diff --git a/tests/AccountTest.php b/tests/AccountTest.php new file mode 100644 index 0000000..aa191d8 --- /dev/null +++ b/tests/AccountTest.php @@ -0,0 +1,48 @@ +client->append(new Response(200, [], '{"blah":"hello"}')); + + $response = $this->client->get_accounts(); + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/accounts'); + } + + // #fetch_account + public function testFetchAccountBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->fetch_account(['account_id' => '1234']); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/accounts/1234'); + } + + public function testFetchAccountWithAccountIDBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->fetch_account(1234); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/accounts/1234'); + } + + public function testFetchAccountMissingId() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $this->client->fetch_account([]); + } +} diff --git a/tests/BroastcastTest.php b/tests/BroastcastTest.php new file mode 100644 index 0000000..b0789ca --- /dev/null +++ b/tests/BroastcastTest.php @@ -0,0 +1,39 @@ +client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->get_broadcasts(); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/broadcasts'); + } + + public function testGetBroastcastsWithParams() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->get_broadcasts(['status' => 'all', 'direction' => 'desc', 'sort' => 'created_at']); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/broadcasts?status=all&direction=desc&sort=created_at'); + } + + public function testFetchBroastcastsBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->fetch_broadcast(['broadcast_id' => '1234']); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/broadcasts/1234'); + } +} diff --git a/tests/CampaignTest.php b/tests/CampaignTest.php new file mode 100644 index 0000000..19c58aa --- /dev/null +++ b/tests/CampaignTest.php @@ -0,0 +1,107 @@ +client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->get_campaigns([]); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/campaigns'); + } + + public function testGetCampaignsValidStatus() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->get_campaigns(['status' => 'active']); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/campaigns?status=active'); + } + + public function testGetCampaignsInvalidStatus() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $this->client->get_campaigns(['status' => 'blah']); + } + + public function testGetCampaignsArbitraryParam() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $response = $this->client->get_campaigns(['myparam' => 'blah']); + } + + // #fetch_campaign + + public function testFetchCampaignBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->fetch_campaign(['campaign_id' => 13579]); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/campaigns/13579'); + } + + public function testFetchCampaignMissingId() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $this->client->fetch_campaign([]); + } + + // #activate_campaign + + public function testActivate_campaignBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->activate_campaign(['campaign_id' => 13579]); + + $this->assertTrue($response->is_success()); + $this->assertRequest('http://api.example.com/v9001/12345/campaigns/13579/activate', 'POST'); + } + + public function testActivate_campaignMissingId() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $this->client->activate_campaign([]); + } + + // #pause_campaign + + public function testPause_campaignBaseCase() + { + $this->client->append(new Response(204, [])); + $response = $this->client->pause_campaign(['campaign_id' => 13579]); + + $this->assertTrue($response->is_success()); + $this->assertRequest('http://api.example.com/v9001/12345/campaigns/13579/pause', 'POST'); + } + + public function testPause_campaignMissingId() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $this->client->pause_campaign([]); + } + + // TODO: Write test cases for fetching campaign_subscribers + + public function testCampaign_subscribersBaseCase() + { + $mocked_requests = []; + } +} diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 6467b87..e33524f 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -2,14 +2,10 @@ namespace DripTests; -use PHPUnit\Framework\TestCase; - +use DripTests\support\DripClientTestBase; use GuzzleHttp\Psr7\Response; -use GuzzleHttp\Psr7\Request; - -require_once 'GuzzleHelpers.php'; -final class ClientTest extends TestCase +final class ClientTest extends DripClientTestBase { public function testInitializedWithApiToken() { @@ -29,435 +25,22 @@ public function testInvalidAccountId() new \Drip\Client("abc123", ""); } - public function testErrorResponseReturned() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - // default client request option "http_errors" will throw - // GuzzleHttp\Exception\ClientException but we set it false so - // no exception is thrown. - new Response(401, [], '{"error":"hello"}'), - new Response(502, [], 'timeout'), - ]); - $response401 = $client->fetch_campaign(['campaign_id' => 1]); - $this->assertFalse($response401->is_success()); - $response502 = $client->fetch_campaign(['campaign_id' => 1]); - $this->assertFalse($response502->is_success()); - } - - ////////////////////////// C A M P A I G N S ////////////////////////// - - // #get_campaigns - - public function testGetCampaignsBaseCase() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->get_campaigns([]); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $uri = $mocked_requests[0]['request']->getUri(); - $this->assertEquals('http://api.example.com/v9001/12345/campaigns', $uri); - } - - public function testGetCampaignsValidStatus() + public function testStaticClientEnvSetup() { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->get_campaigns(['status' => 'active']); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $uri = $mocked_requests[0]['request']->getUri(); - $this->assertEquals('http://api.example.com/v9001/12345/campaigns?status=active', $uri); + putenv('DRIP_API_TOKEN=abc123'); + putenv('DRIP_ACCOUNT_ID=1234'); + \Drip\Client::init_client(); + $this->assertTrue(\Drip\Client::is_initialized()); } - public function testGetCampaignsInvalidStatus() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $this->expectException(\Drip\Exception\InvalidArgumentException::class); - $client->get_campaigns(['status' => 'blah']); - } - - public function testGetCampaignsArbitraryParam() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->get_campaigns(['myparam' => 'blah']); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $uri = $mocked_requests[0]['request']->getUri(); - $this->assertEquals('http://api.example.com/v9001/12345/campaigns?myparam=blah', $uri); - } - - // #fetch_campaign - - public function testFetchCampaignBaseCase() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->fetch_campaign(['campaign_id' => 13579]); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $uri = $mocked_requests[0]['request']->getUri(); - $this->assertEquals('http://api.example.com/v9001/12345/campaigns/13579', $uri); - } - - public function testFetchCampaignMissingId() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $this->expectException(\Drip\Exception\InvalidArgumentException::class); - $client->fetch_campaign([]); - } - - ////////////////////////// A C C O U N T S ////////////////////////// - - // #get_accounts - - public function testGetAccountsBaseCase() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->get_accounts(); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $uri = $mocked_requests[0]['request']->getUri(); - $this->assertEquals('http://api.example.com/v9001/accounts', $uri); - } - - ////////////////////////// S U B S C R I B E R S ////////////////////////// - - // #create_or_update_subscriber - - public function testCreateOrUpdateSubscriberBaseCase() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->create_or_update_subscriber(['blahparam' => 'blahvalue']); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $req = $mocked_requests[0]['request']; - $this->assertEquals('http://api.example.com/v9001/12345/subscribers', $req->getUri()); - $this->assertEquals('POST', $req->getMethod()); - $this->assertEquals('{"subscribers":[{"blahparam":"blahvalue"}]}', (string) $req->getBody()); - } - - // #create_or_update_subscribers - - public function testCreateOrUpdateSubscribersBaseCase() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->create_or_update_subscribers(['batches' => [['subscribers' => [['blah1' => 'blah111'],['blah2' => 'blah222']]]]]); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $req = $mocked_requests[0]['request']; - $this->assertEquals('http://api.example.com/v9001/12345/subscribers/batches', $req->getUri()); - $this->assertEquals('POST', $req->getMethod()); - $this->assertEquals('{"batches":[{"subscribers":[{"blah1":"blah111"},{"blah2":"blah222"}]}]}', (string) $req->getBody()); - } - - // #fetch_subscriber - - public function testFetchSubscriberById() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->fetch_subscriber(['subscriber_id' => '1234']); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $req = $mocked_requests[0]['request']; - $this->assertEquals('http://api.example.com/v9001/12345/subscribers/1234', $req->getUri()); - $this->assertEquals('GET', $req->getMethod()); - } - - public function testFetchSubscriberByEmail() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->fetch_subscriber(['email' => 'test@example.com']); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $req = $mocked_requests[0]['request']; - $this->assertEquals('http://api.example.com/v9001/12345/subscribers/test%40example.com', $req->getUri()); - $this->assertEquals('GET', $req->getMethod()); - } - - public function testFetchSubscriberWithNeitherEmailNorId() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $this->expectException(\Drip\Exception\InvalidArgumentException::class); - $response = $client->fetch_subscriber([]); - } - - // #fetch_subscribers - - public function testFetchSubscribers() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->fetch_subscribers(); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - $this->assertCount(1, $mocked_requests); - $req = $mocked_requests[0]['request']; - $this->assertEquals('http://api.example.com/v9001/12345/subscribers', $req->getUri()); - $this->assertEquals('GET', $req->getMethod()); - } - - // #subscribe_subscriber - - public function testSubscribeSubscriberBaseCase() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->subscribe_subscriber(['campaign_id' => '1234', 'email' => 'test@example.com']); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $req = $mocked_requests[0]['request']; - $this->assertEquals('http://api.example.com/v9001/12345/campaigns/1234/subscribers', $req->getUri()); - $this->assertEquals('POST', $req->getMethod()); - $this->assertEquals('{"subscribers":[{"email":"test@example.com","double_optin":true}]}', (string) $req->getBody()); - } - - public function testSubscribeSubscriberWithDoubleOptin() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->subscribe_subscriber(['campaign_id' => '1234', 'email' => 'test@example.com', 'double_optin' => false]); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $req = $mocked_requests[0]['request']; - $this->assertEquals('http://api.example.com/v9001/12345/campaigns/1234/subscribers', $req->getUri()); - $this->assertEquals('POST', $req->getMethod()); - $this->assertEquals('{"subscribers":[{"email":"test@example.com","double_optin":false}]}', (string) $req->getBody()); - } - - public function testSubscribeSubscriberWithoutCampaignId() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $this->expectException(\Drip\Exception\InvalidArgumentException::class); - $client->subscribe_subscriber(['email' => 'test@example.com', 'double_optin' => false]); - } - - public function testSubscribeSubscriberWithoutEmail() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $this->expectException(\Drip\Exception\InvalidArgumentException::class); - $client->subscribe_subscriber(['campaign_id' => '1234', 'double_optin' => false]); - } - - // #unsubscribe_subscriber - - public function testUnsubscribeSubscriberById() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->unsubscribe_subscriber(['subscriber_id' => '1234']); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $req = $mocked_requests[0]['request']; - $this->assertEquals('http://api.example.com/v9001/12345/subscribers/1234/unsubscribe', $req->getUri()); - $this->assertEquals('POST', $req->getMethod()); - } - - public function testUnsubscribeSubscriberByEmail() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->unsubscribe_subscriber(['email' => 'test@example.com']); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $req = $mocked_requests[0]['request']; - $this->assertEquals('http://api.example.com/v9001/12345/subscribers/test%40example.com/unsubscribe', $req->getUri()); - $this->assertEquals('POST', $req->getMethod()); - } - - public function testUnsubscribeSubscriberWithNeitherEmailNorId() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $this->expectException(\Drip\Exception\InvalidArgumentException::class); - $response = $client->unsubscribe_subscriber([]); - } - - // #tag_subscriber - - public function testTagSubscriberBaseCase() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->tag_subscriber(['email' => 'test@example.com', 'tag' => 'blahblah']); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $req = $mocked_requests[0]['request']; - $this->assertEquals('http://api.example.com/v9001/12345/tags', $req->getUri()); - $this->assertEquals('POST', $req->getMethod()); - $this->assertEquals('{"tags":[{"email":"test@example.com","tag":"blahblah"}]}', (string) $req->getBody()); - } - - public function testTagSubscriberWithoutEmail() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $this->expectException(\Drip\Exception\InvalidArgumentException::class); - $response = $client->tag_subscriber(['tag' => 'blahblah']); - } - - public function testTagSubscriberWithoutTag() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $this->expectException(\Drip\Exception\InvalidArgumentException::class); - $response = $client->tag_subscriber(['email' => 'test@example.com']); - } - - // #untag_subscriber - - public function testUntagSubscriberBaseCase() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->untag_subscriber(['email' => 'test@example.com', 'tag' => 'blahblah']); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $req = $mocked_requests[0]['request']; - $this->assertEquals('http://api.example.com/v9001/12345/tags', $req->getUri()); - $this->assertEquals('DELETE', $req->getMethod()); - $this->assertEquals('{"tags":[{"email":"test@example.com","tag":"blahblah"}]}', (string) $req->getBody()); - } - - public function testUntagSubscriberWithoutEmail() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $this->expectException(\Drip\Exception\InvalidArgumentException::class); - $response = $client->untag_subscriber(['tag' => 'blahblah']); - } - - public function testUntagSubscriberWithoutTag() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $this->expectException(\Drip\Exception\InvalidArgumentException::class); - $response = $client->untag_subscriber(['email' => 'test@example.com']); - } - - ////////////////////////// E V E N T S ////////////////////////// - - // #record_event - - public function testRecordEventBaseCase() - { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $response = $client->record_event(['action' => 'blahaction']); - $this->assertTrue($response->is_success()); - $this->assertEquals('hello', $response->get_contents()['blah']); - - $this->assertCount(1, $mocked_requests); - $req = $mocked_requests[0]['request']; - $this->assertEquals('http://api.example.com/v9001/12345/events', $req->getUri()); - $this->assertEquals('POST', $req->getMethod()); - $this->assertEquals('{"events":[{"action":"blahaction"}]}', (string) $req->getBody()); - } - - public function testRecordEventMissingAction() + public function testErrorResponseReturned() { - $mocked_requests = []; - $client = GuzzleHelpers::mocked_client($mocked_requests, [ - new Response(200, [], '{"blah":"hello"}'), - ]); - $this->expectException(\Drip\Exception\InvalidArgumentException::class); - $client->record_event([]); + $this->client->append(new Response(401, [], '{"error":"hello"}')); + $this->client->append(new Response(502, [], 'timeout')); + $response401 = $this->client->fetch_campaign(['campaign_id' => 1]); + $this->assertFalse($response401->is_success()); + $response502 = $this->client->fetch_campaign(['campaign_id' => 1]); + $this->assertFalse($response502->is_success()); } } diff --git a/tests/ConversionTest.php b/tests/ConversionTest.php new file mode 100644 index 0000000..84436ec --- /dev/null +++ b/tests/ConversionTest.php @@ -0,0 +1,30 @@ +client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->get_conversions(); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/goals'); + } + + public function testFetchConversionBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->fetch_conversion(['conversion_id' => '6789']); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/goals/6789'); + } +} diff --git a/tests/CustomFieldsTest.php b/tests/CustomFieldsTest.php new file mode 100644 index 0000000..a723b4a --- /dev/null +++ b/tests/CustomFieldsTest.php @@ -0,0 +1,19 @@ +client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->get_custom_fields(); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/custom_field_identifiers'); + } +} diff --git a/tests/EventTest.php b/tests/EventTest.php new file mode 100644 index 0000000..e63cf3e --- /dev/null +++ b/tests/EventTest.php @@ -0,0 +1,49 @@ +client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->get_event_actions(['per_page' => 1000]); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/event_actions?per_page=1000'); + } + + public function testRecordEventBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->record_event([ + 'action' => 'blahaction', + 'email' => 'testemail@test.com', + 'properties' => ['affiliate_code' => 'XYZ'], + 'occurred_at' => '2014-03-22T03:00:00Z' + ]); + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest( + 'http://api.example.com/v9001/12345/events', + 'POST', + '{"events": [ + {"occurred_at":"2014-03-22T03:00:00Z", + "properties":{"affiliate_code":"XYZ"}, + "email": "testemail@test.com", + "action": "blahaction"}] + }' + ); + } + + public function testRecordEventMissingAction() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $this->client->record_event([]); + } +} diff --git a/tests/FormTest.php b/tests/FormTest.php new file mode 100644 index 0000000..4183279 --- /dev/null +++ b/tests/FormTest.php @@ -0,0 +1,29 @@ +client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->get_forms(); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/forms'); + } + + public function testFetchFormBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->fetch_form('1234'); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/forms/1234'); + } +} diff --git a/tests/OrderTest.php b/tests/OrderTest.php new file mode 100644 index 0000000..9d26b83 --- /dev/null +++ b/tests/OrderTest.php @@ -0,0 +1,97 @@ + 'my_custom_platform', + 'email' => 'user@gmail.com', + 'action' => 'placed', + 'occurred_at' => '2019-01-17T20:50:00Z', + 'order_id' => '456445746', + 'order_public_id' => '#5', + 'grand_total' => 22.99, + 'total_discounts' => 5.34, + 'total_taxes' => 1.0, + 'total_fees' => 2.0, + 'total_shipping' => 5.0, + 'currency' => 'USD', + 'order_url' => 'https://mysuperstore.com/order/456445746', + 'items' => [ + [ + 'product_id' => 'B01J4SWO1G', + 'product_variant_id' => 'B01J4SWO1G-CW-BOTT', + 'sku' => 'XHB-1234', + 'name' => 'The Coolest Water Bottle', + 'brand' => 'Drip', + 'categories' => ['Accessories'], + 'price' => 11.16, + 'sale_price' => 10.16, + 'quantity' => 2, + 'discounts' => 5.34, + 'taxes' => 1.0, + 'fees' => 0.5, + 'shipping' => 5.0, + 'total' => 23.99, + 'product_url' => 'https://mysuperstore.com/dp/B01J4SWO1G', + 'image_url' => 'https://www.getdrip.com/images/example_products/water_bottle.png', + 'product_tag' => 'Best Seller', + ] + ], + 'billing_address' => [ + 'label' => 'Primary Billing', + 'first_name' => 'Bill', + 'last_name' => 'Billington', + 'company' => 'Bills R US', + 'address_1' => '123 Bill St.', + 'address_2' => 'Apt. B', + 'city' => 'Billtown', + 'state' => 'CA', + 'postal_code' => '01234', + 'country' => 'United States', + 'phone' => '555-555-5555', + ], + 'shipping_address' => [ + 'label' => 'Downtown Office', + 'first_name' => 'Ship', + 'last_name' => 'Shipington', + 'company' => 'Shipping 4 Less', + 'address_1' => '123 Ship St.', + 'city' => 'Shipville', + 'state' => 'CA', + 'postal_code' => '01234', + 'country' => 'United States', + 'phone' => '555-555-5555', + ], + ]; + + + public function testCreateOrUpdateOrderBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + + $response = $this->client->create_order_activity_event($this->order); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $expectedBody = json_encode($this->order); + $this->assertRequest('https://api.getdrip.com/v3/12345/shopper_activity/order', 'POST', $expectedBody); + } + + public function testCreateOrUpdateOrdersBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + + $response = $this->client->create_order_activity_events([$this->order, $this->order]); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $expectedBody = json_encode(['orders' => [$this->order, $this->order]]); + $this->assertRequest('https://api.getdrip.com/v3/12345/shopper_activity/order/batch', 'POST', $expectedBody); + } +} diff --git a/tests/SubscriberTest.php b/tests/SubscriberTest.php new file mode 100644 index 0000000..147beb1 --- /dev/null +++ b/tests/SubscriberTest.php @@ -0,0 +1,236 @@ +client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->create_or_update_subscriber(['id' => '1212', 'blahparam' => 'blahvalue']); + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + + $this->assertRequest( + 'http://api.example.com/v9001/12345/subscribers', + 'POST', + '{"subscribers":[{"id":"1212","blahparam":"blahvalue"}]}' + ); + } + + // #create_or_update_subscribers + + public function testCreateOrUpdateSubscribersBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->create_or_update_subscribers(['batches' => [['subscribers' => [['blah1' => 'blah111'], ['blah2' => 'blah222']]]]]); + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest( + 'http://api.example.com/v9001/12345/subscribers/batches', + 'POST', + '{"batches":[{"subscribers":[{"blah1":"blah111"},{"blah2":"blah222"}]}]}' + ); + } + + public function testBatchCreateOrUpdateSubscribersBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->batch_create_or_update_subscribers([['id' => '1212', 'blah1' => 'blah111'], ['id' => '1213', 'blah2' => 'blah222']]); + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + + $this->assertRequest( + 'http://api.example.com/v9001/12345/subscribers/batches', + 'POST', + '{"batches":[{"subscribers":[{"id":"1212","blah1":"blah111"},{"id":"1213","blah2":"blah222"}]}]}' + ); + } + + + // #fetch_subscriber + + public function testFetchSubscriberById() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->fetch_subscriber(['subscriber_id' => '1234']); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/subscribers/1234'); + } + + public function testFetchSubscriberByEmail() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->fetch_subscriber(['email' => 'test@example.com']); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/subscribers/test%40example.com'); + } + + public function testFetchSubscriberWithNeitherEmailNorId() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $response = $this->client->fetch_subscriber([]); + } + + // #fetch_subscribers + + public function testFetchSubscribers() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->fetch_subscribers(); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/subscribers'); + } + + // #subscribe_subscriber + + public function testSubscribeSubscriberBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->subscribe_subscriber(['campaign_id' => '1234', 'email' => 'test@example.com']); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest( + 'http://api.example.com/v9001/12345/campaigns/1234/subscribers', + 'POST', + '{"subscribers":[{"email":"test@example.com","double_optin":true}]}' + ); + } + + public function testSubscribeSubscriberWithDoubleOptin() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->subscribe_subscriber(['campaign_id' => '1234', 'email' => 'test@example.com', 'double_optin' => false]); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest( + 'http://api.example.com/v9001/12345/campaigns/1234/subscribers', + 'POST', + '{"subscribers":[{"email":"test@example.com","double_optin":false}]}' + ); + } + + public function testSubscribeSubscriberWithoutCampaignId() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $this->client->subscribe_subscriber(['email' => 'test@example.com', 'double_optin' => false]); + } + + public function testSubscribeSubscriberWithoutEmail() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $this->client->subscribe_subscriber(['campaign_id' => '1234', 'double_optin' => false]); + } + + // #unsubscribe_subscriber + + public function testUnsubscribeSubscriberById() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->unsubscribe_subscriber(['subscriber_id' => '1234']); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/subscribers/1234/unsubscribe', 'POST'); + } + + public function testUnsubscribeSubscriberByEmail() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->unsubscribe_subscriber(['email' => 'test@example.com']); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/12345/subscribers/test%40example.com/unsubscribe', 'POST'); + } + + public function testUnsubscribeSubscriberWithNeitherEmailNorId() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $response = $this->client->unsubscribe_subscriber([]); + } + + // #tag_subscriber + + public function testTagSubscriberBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->tag_subscriber(['email' => 'test@example.com', 'tag' => 'blahblah']); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest( + 'http://api.example.com/v9001/12345/tags', + 'POST', + '{"tags":[{"email":"test@example.com","tag":"blahblah"}]}' + ); + } + + public function testTagSubscriberWithoutEmail() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $response = $this->client->tag_subscriber(['tag' => 'blahblah']); + } + + public function testTagSubscriberWithoutTag() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $response = $this->client->tag_subscriber(['email' => 'test@example.com']); + } + + // #untag_subscriber + + public function testUntagSubscriberBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->untag_subscriber(['email' => 'test@example.com', 'tag' => 'blahblah']); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest( + 'http://api.example.com/v9001/12345/tags', + 'DELETE', + '{"tags":[{"email":"test@example.com","tag":"blahblah"}]}' + ); + } + + public function testUntagSubscriberWithoutEmail() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $response = $this->client->untag_subscriber(['tag' => 'blahblah']); + } + + public function testUntagSubscriberWithoutTag() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $this->expectException(\Drip\Exception\InvalidArgumentException::class); + $response = $this->client->untag_subscriber(['email' => 'test@example.com']); + } + + public function testCampaignSubscriptionsBaseCase() + { + $this->client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->campaign_subscriptions('9876'); + $this->assertRequest('http://api.example.com/v9001/12345/subscribers/9876/campaign_subscriptions'); + } +} diff --git a/tests/UserTest.php b/tests/UserTest.php new file mode 100644 index 0000000..37c6ffc --- /dev/null +++ b/tests/UserTest.php @@ -0,0 +1,19 @@ +client->append(new Response(200, [], '{"blah":"hello"}')); + $response = $this->client->fetch_user(); + + $this->assertTrue($response->is_success()); + $this->assertEquals('hello', $response->get_contents()['blah']); + $this->assertRequest('http://api.example.com/v9001/user'); + } +} diff --git a/tests/support/DripClientTestBase.php b/tests/support/DripClientTestBase.php new file mode 100644 index 0000000..df45c14 --- /dev/null +++ b/tests/support/DripClientTestBase.php @@ -0,0 +1,44 @@ +client = new GuzzleHelpers(); + } + + /** + * @param string $expectedUrl + * @param string $expectedmethod + * @param string $expectedBody + * @param string $expectedBodyType + * @param RequestInterface $actualRequest + */ + public function assertRequest($expectedUrl, $expectedmethod = 'GET', $expectedBody = null, $expectedBodyType = 'JSON', $actualRequest = null) + { + if ($actualRequest === null) { + $actualRequest = $this->client->getLastRequest(); + } + + $this->assertEquals($expectedUrl, $actualRequest->getUri()); + $this->assertEquals($expectedmethod, $actualRequest->getMethod()); + if ($expectedBody !== null) { + switch ($expectedBodyType) { + case 'JSON': + $this->assertJsonStringEqualsJsonString($expectedBody, (string) $actualRequest->getBody()); + break; + default: + $this->assertEquals($expectedBody, $actualRequest->getBody()); + break; + } + } + } +} diff --git a/tests/support/GuzzleHelpers.php b/tests/support/GuzzleHelpers.php index 9cecc7d..9373313 100644 --- a/tests/support/GuzzleHelpers.php +++ b/tests/support/GuzzleHelpers.php @@ -1,30 +1,61 @@ mock = new MockHandler(); + $stack = HandlerStack::create($this->mock); + $stack->push(\GuzzleHttp\Middleware::history($this->history)); + + + parent::__construct("abc123", 12345, [ 'api_end_point' => 'http://api.example.com/v9001/', - 'guzzle_stack_constructor' => function () use (&$history_object, $responses) { - $mock = new MockHandler($responses); - $stack = \GuzzleHttp\HandlerStack::create($mock); - $stack->push(\GuzzleHttp\Middleware::history($history_object)); + 'guzzle_stack_constructor' => function () use ($stack) { return $stack; } ]); } + + /** + * @return \Psr\Http\Message\UriInterface + */ + public function getLastUri() + { + return $this->mock->getLastRequest()->getUri(); + } + + /** + * @return \Psr\Http\Message\RequestInterface + */ + public function getLastRequest() + { + return $this->mock->getLastRequest(); + } + + /** + * @param $a + */ + public function append($a) + { + $this->mock->append($a); + } }