<?php

namespace AuthStack\OAuth2\Model\Protocol\Grant\tests\units;

use AuthStack\OAuth2\Model\Protocol\Request\ClientCredentials\GrantRequest;
use AuthStack\OAuth2\Model\Protocol\Response\ClientCredentials\GrantResponse;
use mageekguy\atoum;
use Illuminate\Http\Request;
use AuthStack\OAuth2\Exception\OAuth2Exception;
use AuthStack\OAuth2\Model\Protocol\Grant\GrantFactory;

class ClientCredentials extends atoum\test
{
    public function testCreateClientCredentialsRequest()
    {
        $this->given($ccreds = (new GrantFactory())->clientCredentials()->grantRequest())
            ->then
                ->object($ccreds)->isInstanceOf(GrantRequest::class)
                ->object($ccreds->setScope('read write'))->isInstanceOf(GrantRequest::class)
                ->array($ccreds->toArray())->hasKeys(['grant_type', 'scope'])
            ;
    }

    public function testReceiveClientCredentialsRequest()
    {
        $this->given($model = ['grant_type' => 'client_credentials', 'scope' => 'read write'])
            ->and($request = Request::create('https://your.authorization.server/token', 'GET', $model))
            ->and($factory = (new GrantFactory())->clientCredentials()->grantRequest())
            ->then
                ->object($ccreds = $factory->receive($request))->isInstanceOf(GrantRequest::class)
                ->string($ccreds->getScope())->isEqualTo('read write')
                ->array($ccreds->toArray())->hasKeys(['grant_type', 'scope'])
            ;
    }

    public function testReceiveClientCredentialsRequestFails()
    {
        $this->given($model = ['grant_type' => 'client_credentials->this is bad', 'scope' => 'read write'])
            ->and($request = Request::create('https://your.authorization.server/token', 'GET', $model))
            ->and($factory = (new GrantFactory())->clientCredentials()->grantRequest())
            ->then
                ->exception(function() use ($request, $factory)
                {
                    $ccreds = $factory->receive($request);
                })->isInstanceOf(OAuth2Exception::class)
            ;
    }

    public function testCreateClientCredentialsResponse()
    {
        $this->given($response = (new GrantFactory())->clientCredentials()->grantResponse())
            ->then
                ->object($response)->isInstanceOf(GrantResponse::class)
                ->object($response->setAccessToken('this_is_access_token')->setExpiresIn(300)->setTokenType('bearer'))->isInstanceOf(GrantResponse::class)
                ->array($response->toArray())
                    ->hasKeys(['access_token', 'token_type', 'expires_in'])
            ;
    }

    public function testReceiveClientCredentialsResponse()
    {
        $this->given($model = ['access_token' => 'first', 'token_type' => 'bearer', 'expires_in' => 200])
            ->and($request = Request::create('https://your.relying.party/callback', 'GET', $model))
            ->then
                ->object($response = (new GrantFactory())->clientCredentials()->grantResponse()->receive($request))->isInstanceOf(GrantResponse::class)
                ->string($response->getAccessToken())->isEqualTo('first')
                ->string($response->getTokenType())->isEqualTo('bearer')
                ->integer($response->getExpiresIn())->isEqualTo(200)
            ;
    }
}