mirror of
https://github.com/wearepixel/laravel-quickbooks.git
synced 2026-11-14 14:01:46 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
<?php
|
||||
|
||||
namespace Wearepixel\QuickBooks;
|
||||
|
||||
use Mockery;
|
||||
use Mockery\Mock;
|
||||
use QuickBooksOnline\API\DataService\DataService;
|
||||
use QuickBooksOnline\API\Exception\ServiceException;
|
||||
|
||||
/**
|
||||
* Class ClientTest
|
||||
*/
|
||||
class ClientTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $configs = [];
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $token_mock;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->configs = [
|
||||
'data_service' => [
|
||||
'auth_mode' => 'oauth2',
|
||||
'base_url' => 'Development',
|
||||
'client_id' => 'QUICKBOOKS_CLIENT_ID',
|
||||
'client_secret' => 'QUICKBOOKS_CLIENT_SECRET',
|
||||
'scope' => 'com.intuit.quickbooks.accounting',
|
||||
],
|
||||
];
|
||||
|
||||
$this->token_mock = Mockery::mock(Token::class);
|
||||
|
||||
$this->client = $this->makeClient();
|
||||
}
|
||||
|
||||
private function makeClient($configs = null)
|
||||
{
|
||||
if (! is_null($configs)) {
|
||||
return new Client($configs, $this->token_mock);
|
||||
}
|
||||
|
||||
return new Client($this->configs, $this->token_mock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_can_be_constructed()
|
||||
{
|
||||
$this->assertInstanceOf(Client::class, $this->client);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_returns_a_data_service_configured_to_request_oauth_token_when_token_is_empty()
|
||||
{
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->twice()
|
||||
->with('hasValidAccessToken')
|
||||
->andReturnFalse();
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->once()
|
||||
->with('hasValidRefreshToken')
|
||||
->andReturnFalse();
|
||||
|
||||
$this->assertFalse(
|
||||
$this->client
|
||||
->getDataService()
|
||||
->getServiceContext()
|
||||
->IppConfiguration->Security->isAccessTokenSet(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_caches_the_data_service_once_it_is_made()
|
||||
{
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->twice()
|
||||
->with('hasValidAccessToken')
|
||||
->andReturnFalse();
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->once()
|
||||
->with('hasValidRefreshToken')
|
||||
->andReturnFalse();
|
||||
|
||||
// TODO: Find out if this is the actual goal of this test, to make sure a DataService is received
|
||||
$this->assertEquals(DataService::class, get_class($this->client->getDataService()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_returns_a_data_service_with_oauth_token_when_valid_access_token_exist()
|
||||
{
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->twice()
|
||||
->with('hasValidAccessToken')
|
||||
->andReturnTrue();
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->once()
|
||||
->with('access_token')
|
||||
->andReturn('access_token');
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->once()
|
||||
->with('realm_id')
|
||||
->andReturn('realm_id');
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->once()
|
||||
->with('refresh_token')
|
||||
->andReturn('refresh_token');
|
||||
|
||||
$this->assertTrue(
|
||||
$this->client
|
||||
->getDataService()
|
||||
->getServiceContext()
|
||||
->IppConfiguration->Security->isAccessTokenSet(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_returns_a_data_service_with_refreshed_token_when_access_token_expired_but_refresh_token_valid()
|
||||
{
|
||||
$this->expectException(ServiceException::class);
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->twice()
|
||||
->with('hasValidAccessToken')
|
||||
->andReturnFalse();
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->once()
|
||||
->with('hasValidRefreshToken')
|
||||
->andReturnTrue();
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->never()
|
||||
->with('access_token');
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->once()
|
||||
->with('realm_id')
|
||||
->andReturn('realm_id');
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->once()
|
||||
->with('refresh_token')
|
||||
->andReturn('refresh_token');
|
||||
|
||||
// TODO: This really needs to test that things are getting called correctly on the DataService class
|
||||
$this->assertFalse(
|
||||
$this->client
|
||||
->getDataService()
|
||||
->getServiceContext()
|
||||
->IppConfiguration->Security->isAccessTokenSet(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_returns_a_report_service_using_the_data_service()
|
||||
{
|
||||
$this->markTestSkipped(
|
||||
'Once we figure out how to test around the static DataService::Configure',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_has_logging_off_by_default()
|
||||
{
|
||||
$this->markTestSkipped('Have to figure out how to test this with the new code in 5.x');
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->once()
|
||||
->with('hasValidAccessToken')
|
||||
->andReturnFalse();
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->once()
|
||||
->with('hasValidRefreshToken')
|
||||
->andReturnFalse();
|
||||
|
||||
$this->assertFalse(
|
||||
filter_var(
|
||||
$this->client->getDataService()->getServiceContext()->IppConfiguration->Logger
|
||||
->RequestLog->EnableRequestResponseLogging,
|
||||
FILTER_VALIDATE_BOOLEAN,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_allows_logging_turned_on_and_pointed_to_expected_file()
|
||||
{
|
||||
$this->markTestSkipped('Have to figure out how to test this with the new code in 5.x');
|
||||
|
||||
$this->client = $this->makeClient(
|
||||
array_merge(
|
||||
[
|
||||
'logging' => [
|
||||
'enabled' => true,
|
||||
'location' => '/some/valid/path',
|
||||
],
|
||||
],
|
||||
$this->configs,
|
||||
),
|
||||
);
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->once()
|
||||
->with('hasValidAccessToken')
|
||||
->andReturnFalse();
|
||||
|
||||
$this->token_mock
|
||||
->shouldReceive('getAttribute')
|
||||
->once()
|
||||
->with('hasValidRefreshToken')
|
||||
->andReturnFalse();
|
||||
|
||||
$this->assertTrue(
|
||||
filter_var(
|
||||
$this->client->getDataService()->getServiceContext()->IppConfiguration->Logger
|
||||
->RequestLog->EnableRequestResponseLogging,
|
||||
FILTER_VALIDATE_BOOLEAN,
|
||||
),
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'/some/valid/path',
|
||||
$this->client->getDataService()->getServiceContext()->IppConfiguration->Logger
|
||||
->RequestLog->ServiceRequestLoggingLocation,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_returns_self_after_deleting_token()
|
||||
{
|
||||
$this->token_mock
|
||||
->shouldReceive('remove')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturnSelf();
|
||||
|
||||
$this->assertInstanceOf(Client::class, $this->client->deleteToken());
|
||||
}
|
||||
}
|
||||
|
||||
function dir($path)
|
||||
{
|
||||
return $path === '/some/valid/path';
|
||||
}
|
||||
|
||||
function route($name)
|
||||
{
|
||||
return $name;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Wearepixel\QuickBooks;
|
||||
|
||||
use Wearepixel\QuickBooks\Stubs\User;
|
||||
|
||||
/**
|
||||
* Class HasQuickBooksTokenTest
|
||||
*/
|
||||
class HasQuickBooksTokenTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->user = new User();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_can_be_constructed()
|
||||
{
|
||||
$this->assertInstanceOf(User::class, $this->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_has_a_hasOne_relationship_to_token()
|
||||
{
|
||||
$this->assertInstanceOf(Token::class, $this->user->quickBooksToken()->getModel());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
|
||||
namespace Wearepixel\QuickBooks\Http\Controllers;
|
||||
|
||||
use Illuminate\Contracts\Routing\UrlGenerator;
|
||||
use Illuminate\Contracts\View\Factory as ViewFactory;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Session\Store;
|
||||
use Mockery;
|
||||
use Mockery\Mock;
|
||||
use QuickBooksOnline\API\DataService\DataService;
|
||||
use Wearepixel\QuickBooks\Client as QuickBooks;
|
||||
use Wearepixel\QuickBooks\TestCase;
|
||||
|
||||
/**
|
||||
* Class ControllerTest
|
||||
*/
|
||||
class ControllerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Controller
|
||||
*/
|
||||
protected $controller;
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $data_service_mock;
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $quickbooks_mock;
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $redirector_mock;
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $request_mock;
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $session_mock;
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $view_factory_mock;
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $view_mock;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->data_service_mock = Mockery::mock(DataService::class);
|
||||
$this->quickbooks_mock = Mockery::mock(QuickBooks::class);
|
||||
$this->redirector_mock = Mockery::mock(Redirector::class);
|
||||
$this->request_mock = Mockery::mock(Request::class);
|
||||
$this->session_mock = Mockery::mock(Store::class);
|
||||
$this->view_factory_mock = Mockery::mock(ViewFactory::class);
|
||||
$this->view_mock = Mockery::mock(View::class);
|
||||
|
||||
$this->controller = new Controller();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_can_be_constructed()
|
||||
{
|
||||
$this->assertInstanceOf(Controller::class, $this->controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_shows_view_to_connect_if_account_not_linked()
|
||||
{
|
||||
$this->data_service_mock
|
||||
->shouldReceive('getCompanyInfo')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturn([
|
||||
'name' => 'Company',
|
||||
]);
|
||||
|
||||
$this->quickbooks_mock
|
||||
->shouldReceive('hasValidRefreshToken')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturnTrue();
|
||||
|
||||
$this->quickbooks_mock
|
||||
->shouldReceive('getDataService')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturn($this->data_service_mock);
|
||||
|
||||
$this->view_factory_mock
|
||||
->shouldReceive('make')
|
||||
->once()
|
||||
->with('quickbooks::disconnect')
|
||||
->andReturn($this->view_mock);
|
||||
|
||||
$this->view_mock
|
||||
->shouldReceive('with')
|
||||
->once()
|
||||
->withArgs([
|
||||
'company',
|
||||
[
|
||||
'name' => 'Company',
|
||||
],
|
||||
])
|
||||
->andReturnSelf();
|
||||
|
||||
$this->controller->connect($this->quickbooks_mock, $this->view_factory_mock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_shows_view_to_disconnect_if_account_linked()
|
||||
{
|
||||
$this->quickbooks_mock
|
||||
->shouldReceive('hasValidRefreshToken')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturnFalse();
|
||||
|
||||
$this->quickbooks_mock
|
||||
->shouldReceive('authorizationUri')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturn('http://uri');
|
||||
|
||||
$this->view_factory_mock
|
||||
->shouldReceive('make')
|
||||
->once()
|
||||
->with('quickbooks::connect')
|
||||
->andReturn($this->view_mock);
|
||||
|
||||
$this->view_mock
|
||||
->shouldReceive('with')
|
||||
->once()
|
||||
->withArgs(['authorization_uri', 'http://uri'])
|
||||
->andReturnSelf();
|
||||
|
||||
$this->controller->connect($this->quickbooks_mock, $this->view_factory_mock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_disconnects_from_quickbooks_when_requested()
|
||||
{
|
||||
$this->request_mock
|
||||
->shouldReceive('session')
|
||||
->once()
|
||||
->andReturn($this->session_mock);
|
||||
|
||||
$this->session_mock
|
||||
->shouldReceive('flash')
|
||||
->once()
|
||||
->withAnyArgs();
|
||||
|
||||
$this->redirector_mock
|
||||
->shouldReceive('back')
|
||||
->once()
|
||||
->andReturn(new RedirectResponse('/test', 302));
|
||||
|
||||
$this->quickbooks_mock
|
||||
->shouldReceive('deleteToken')
|
||||
->once()
|
||||
->withNoArgs();
|
||||
|
||||
$result = $this->controller->disconnect(
|
||||
$this->redirector_mock,
|
||||
$this->request_mock,
|
||||
$this->quickbooks_mock,
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(RedirectResponse::class, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_finishes_connecting_to_quickbooks_when_given_a_valid_token_by_quickbooks()
|
||||
{
|
||||
$this->url_generator_mock = Mockery::mock(UrlGenerator::class);
|
||||
$realmId = random_int(1, 9999);
|
||||
|
||||
$this->quickbooks_mock
|
||||
->shouldReceive('exchangeCodeForToken')
|
||||
->once()
|
||||
->withArgs(['code', $realmId]);
|
||||
|
||||
$this->request_mock
|
||||
->shouldReceive('get')
|
||||
->once()
|
||||
->withArgs(['code'])
|
||||
->andReturn('code');
|
||||
|
||||
$this->request_mock
|
||||
->shouldReceive('get')
|
||||
->once()
|
||||
->withArgs(['realmId'])
|
||||
->andReturn($realmId);
|
||||
|
||||
$this->request_mock
|
||||
->shouldReceive('session')
|
||||
->once()
|
||||
->andReturn($this->session_mock);
|
||||
|
||||
$this->session_mock
|
||||
->shouldReceive('flash')
|
||||
->once()
|
||||
->withAnyArgs();
|
||||
|
||||
$this->redirector_mock
|
||||
->shouldReceive('intended')
|
||||
->once()
|
||||
->withAnyArgs()
|
||||
->andReturn(new RedirectResponse('/test', 302));
|
||||
|
||||
$this->url_generator_mock
|
||||
->shouldReceive('route')
|
||||
->withArgs(['quickbooks.connect'])
|
||||
->once();
|
||||
|
||||
$result = $this->controller->token(
|
||||
$this->redirector_mock,
|
||||
$this->request_mock,
|
||||
$this->quickbooks_mock,
|
||||
$this->url_generator_mock,
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(RedirectResponse::class, $result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace Wearepixel\QuickBooks\Http\Middleware;
|
||||
|
||||
use Illuminate\Contracts\Routing\UrlGenerator;
|
||||
use Illuminate\Contracts\Session\Session;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Mockery;
|
||||
use Mockery\Mock;
|
||||
use Wearepixel\QuickBooks\Client as QuickBooks;
|
||||
use Wearepixel\QuickBooks\TestCase;
|
||||
|
||||
/**
|
||||
* Class FilterTest
|
||||
*/
|
||||
class FilterTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Filter
|
||||
*/
|
||||
protected $filter;
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $quickbooks_mock;
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $redirector_mock;
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $request_mock;
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $session_mock;
|
||||
|
||||
/**
|
||||
* @var Mock
|
||||
*/
|
||||
protected $url_generator_mock;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->quickbooks_mock = Mockery::mock(QuickBooks::class);
|
||||
$this->redirector_mock = Mockery::mock(Redirector::class);
|
||||
$this->request_mock = Mockery::mock(Request::class);
|
||||
$this->session_mock = Mockery::mock(Session::class);
|
||||
$this->url_generator_mock = Mockery::mock(UrlGenerator::class);
|
||||
|
||||
$this->filter = new Filter(
|
||||
$this->quickbooks_mock,
|
||||
$this->redirector_mock,
|
||||
$this->session_mock,
|
||||
$this->url_generator_mock,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_can_be_constructed()
|
||||
{
|
||||
$this->assertInstanceOf(Filter::class, $this->filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_just_passes_the_request_to_the_next_middleware_if_account_linked_to_quickbooks()
|
||||
{
|
||||
$next_middleware = function ($request) {
|
||||
$this->assertEquals($this->request_mock, $request);
|
||||
};
|
||||
|
||||
$this->quickbooks_mock
|
||||
->shouldReceive('hasValidRefreshToken')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturnTrue();
|
||||
|
||||
$this->filter->handle($this->request_mock, $next_middleware);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_redirects_to_quickbooks_connect_route_after_setting_intended_session_if_account_not_linked()
|
||||
{
|
||||
$this->request_mock
|
||||
->shouldReceive('path')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturn('path');
|
||||
|
||||
$this->url_generator_mock
|
||||
->shouldReceive('to')
|
||||
->once()
|
||||
->with('path')
|
||||
->andReturn('http://to/path');
|
||||
|
||||
$this->session_mock
|
||||
->shouldReceive('put')
|
||||
->once()
|
||||
->withArgs(['url.intended', 'http://to/path'])
|
||||
->andReturnNull();
|
||||
|
||||
$this->redirector_mock
|
||||
->shouldReceive('route')
|
||||
->once()
|
||||
->with('quickbooks.connect')
|
||||
->andReturnSelf();
|
||||
|
||||
$next_middleware = function ($request) {
|
||||
// If this is called, then fail test
|
||||
$this->assertTrue(false);
|
||||
};
|
||||
|
||||
$this->quickbooks_mock
|
||||
->shouldReceive('hasValidRefreshToken')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturnFalse();
|
||||
|
||||
$this->filter->handle($this->request_mock, $next_middleware);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Wearepixel\QuickBooks\Stubs;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Mockery;
|
||||
use Wearepixel\QuickBooks\Token;
|
||||
|
||||
/**
|
||||
* Class TokenStub
|
||||
*
|
||||
* Stub for a Laravel Token model
|
||||
*/
|
||||
class TokenStub extends Token
|
||||
{
|
||||
// Put public properties on this stub to keep the Model from trying to get them from db
|
||||
public $access_token = null;
|
||||
|
||||
public $access_token_expires_at = null;
|
||||
|
||||
public $realm_id = null;
|
||||
|
||||
public $refresh_token = null;
|
||||
|
||||
public $refresh_token_expires_at = null;
|
||||
|
||||
public $user = null;
|
||||
|
||||
public function belongsTo(
|
||||
$related,
|
||||
$foreignKey = null,
|
||||
$ownerKey = null,
|
||||
$relation = null,
|
||||
): BelongsTo {
|
||||
$related_mock = Mockery::mock($related);
|
||||
$related_mock->shouldIgnoreMissing();
|
||||
|
||||
$child_mock = Mockery::mock(Model::class);
|
||||
$child_mock->shouldIgnoreMissing();
|
||||
|
||||
$builder_mock = Mockery::mock(Builder::class);
|
||||
$builder_mock->shouldIgnoreMissing();
|
||||
$builder_mock->shouldReceive('getModel')->andReturn($related_mock);
|
||||
|
||||
return new BelongsTo($builder_mock, $child_mock, $foreignKey, $ownerKey, $relation);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Wearepixel\QuickBooks\Stubs;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Mockery;
|
||||
use Wearepixel\QuickBooks\HasQuickBooksToken;
|
||||
|
||||
/**
|
||||
* Class User
|
||||
*
|
||||
* Stub for a Laravel User model
|
||||
*/
|
||||
class User
|
||||
{
|
||||
use HasQuickBooksToken;
|
||||
|
||||
public function hasOne($relationship): HasOne
|
||||
{
|
||||
$related_mock = Mockery::mock($relationship);
|
||||
$related_mock->shouldIgnoreMissing();
|
||||
|
||||
$builder_mock = Mockery::mock(Builder::class);
|
||||
$builder_mock->shouldIgnoreMissing();
|
||||
$builder_mock->shouldReceive('getModel')->andReturn($related_mock);
|
||||
|
||||
$parent_mock = Mockery::mock(Model::class);
|
||||
$parent_mock->shouldIgnoreMissing();
|
||||
|
||||
return new HasOne($builder_mock, $parent_mock, 'foreignKey', 'localKey');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Wearepixel\QuickBooks;
|
||||
|
||||
use ArrayAccess;
|
||||
use Countable;
|
||||
use Iterator;
|
||||
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
|
||||
use Mockery\MockInterface;
|
||||
use PHPUnit\Framework\TestCase as PHPUnitTestCase;
|
||||
|
||||
/**
|
||||
* Class TestCase
|
||||
*/
|
||||
abstract class TestCase extends PHPUnitTestCase
|
||||
{
|
||||
use MockeryPHPUnitIntegration;
|
||||
|
||||
/**
|
||||
* Helper to allow mocking of iterator classes.
|
||||
*
|
||||
* @link https://gist.github.com/VladaHejda/8299871
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function mockArrayIterator(MockInterface $mock, array $items)
|
||||
{
|
||||
if ($mock instanceof ArrayAccess) {
|
||||
foreach ($items as $key => $val) {
|
||||
$mock
|
||||
->shouldReceive('offsetGet')
|
||||
->with($key)
|
||||
->andReturn($val);
|
||||
|
||||
$mock
|
||||
->shouldReceive('offsetExists')
|
||||
->with($key)
|
||||
->andReturn(true);
|
||||
}
|
||||
|
||||
$mock->shouldReceive('offsetExists')->andReturn(false);
|
||||
}
|
||||
|
||||
if ($mock instanceof Iterator) {
|
||||
$counter = 0;
|
||||
|
||||
$mock->shouldReceive('rewind')->andReturnUsing(function () use (&$counter) {
|
||||
$counter = 0;
|
||||
});
|
||||
|
||||
$vals = array_values($items);
|
||||
$keys = array_values(array_keys($items));
|
||||
|
||||
$mock->shouldReceive('valid')->andReturnUsing(function () use (&$counter, $vals) {
|
||||
return isset($vals[$counter]);
|
||||
});
|
||||
|
||||
$mock->shouldReceive('current')->andReturnUsing(function () use (&$counter, $vals) {
|
||||
return $vals[$counter];
|
||||
});
|
||||
|
||||
$mock->shouldReceive('key')->andReturnUsing(function () use (&$counter, $keys) {
|
||||
return $keys[$counter];
|
||||
});
|
||||
|
||||
$mock->shouldReceive('next')->andReturnUsing(function () use (&$counter) {
|
||||
$counter++;
|
||||
});
|
||||
}
|
||||
|
||||
if ($mock instanceof Countable) {
|
||||
$mock->shouldReceive('count')->andReturn(count($items));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace Wearepixel\QuickBooks;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Mockery;
|
||||
use QuickBooksOnline\API\Core\OAuth\OAuth2\OAuth2AccessToken;
|
||||
use Wearepixel\QuickBooks\Stubs\TokenStub;
|
||||
use Wearepixel\QuickBooks\Stubs\User;
|
||||
|
||||
/**
|
||||
* Class TokenTest
|
||||
*/
|
||||
class TokenTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Token
|
||||
*/
|
||||
protected $token;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->token = new TokenStub();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_can_be_constructed()
|
||||
{
|
||||
$this->assertInstanceOf(Token::class, $this->token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_has_accessor_for_valid_access_token()
|
||||
{
|
||||
$this->assertNotNull($this->token->getHasValidAccessTokenAttribute());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_has_accessor_for_valid_refresh_token()
|
||||
{
|
||||
$this->assertNotNull($this->token->getHasValidRefreshTokenAttribute());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_knows_that_the_access_token_expires_at_has_to_be_valid()
|
||||
{
|
||||
$this->assertFalse($this->token->getHasValidAccessTokenAttribute());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_knows_that_the_refresh_token_expires_at_has_to_be_valid()
|
||||
{
|
||||
$this->assertFalse($this->token->getHasValidRefreshTokenAttribute());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_know_if_access_token_expires_at_is_less_than_now_it_is_not_expired()
|
||||
{
|
||||
$now = Carbon::now();
|
||||
Carbon::setTestNow($now);
|
||||
|
||||
$this->token->access_token_expires_at = Carbon::now()->addSecond();
|
||||
|
||||
$this->assertTrue($this->token->getHasValidAccessTokenAttribute());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_know_if_refresh_token_expires_at_is_less_than_now_it_is_not_expired()
|
||||
{
|
||||
$now = Carbon::now();
|
||||
Carbon::setTestNow($now);
|
||||
|
||||
$this->token->refresh_token_expires_at = Carbon::now()->addSecond();
|
||||
|
||||
$this->assertTrue($this->token->getHasValidRefreshTokenAttribute());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_know_if_access_token_expires_at_is_greater_than_or_equal_to_now_it_is_expired()
|
||||
{
|
||||
$now = Carbon::now();
|
||||
Carbon::setTestNow($now);
|
||||
|
||||
$this->token->access_token_expires_at = Carbon::now();
|
||||
|
||||
$this->assertFalse($this->token->getHasValidAccessTokenAttribute());
|
||||
|
||||
$this->token->access_token_expires_at->subSecond();
|
||||
|
||||
$this->assertFalse($this->token->getHasValidAccessTokenAttribute());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_know_if_refresh_token_expires_at_is_greater_than_or_equal_to_now_it_is_expired()
|
||||
{
|
||||
$now = Carbon::now();
|
||||
Carbon::setTestNow($now);
|
||||
|
||||
$this->token->refresh_token_expires_at = Carbon::now();
|
||||
|
||||
$this->assertFalse($this->token->getHasValidRefreshTokenAttribute());
|
||||
|
||||
$this->token->refresh_token_expires_at->subSecond();
|
||||
|
||||
$this->assertFalse($this->token->getHasValidRefreshTokenAttribute());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_stores_the_oauth_token_parts_in_expected_properties()
|
||||
{
|
||||
$oauth_token_mock = Mockery::mock(OAuth2AccessToken::class);
|
||||
|
||||
$oauth_token_mock
|
||||
->shouldReceive('getAccessToken')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturn('access_token');
|
||||
|
||||
$oauth_token_mock
|
||||
->shouldReceive('getAccessTokenExpiresAt')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturn('now');
|
||||
|
||||
$oauth_token_mock
|
||||
->shouldReceive('getRealmID')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturn('realm_id');
|
||||
|
||||
$oauth_token_mock
|
||||
->shouldReceive('getRefreshToken')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturn('refresh_token');
|
||||
|
||||
$oauth_token_mock
|
||||
->shouldReceive('getRefreshTokenExpiresAt')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturn('now');
|
||||
|
||||
$this->token->parseOauthToken($oauth_token_mock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_allows_itself_to_be_deleted_and_returns_new_token()
|
||||
{
|
||||
$this->token->user = Mockery::mock(User::class);
|
||||
|
||||
$has_one_mock = Mockery::mock(HasOne::class);
|
||||
$token_mock = Mockery::mock(Token::class);
|
||||
|
||||
$has_one_mock
|
||||
->shouldReceive('make')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturn($token_mock);
|
||||
|
||||
$this->token->user
|
||||
->shouldReceive('quickBooksToken')
|
||||
->once()
|
||||
->withNoArgs()
|
||||
->andReturn($has_one_mock);
|
||||
|
||||
$this->token->user->id = 1;
|
||||
|
||||
$this->assertEquals($token_mock, $this->token->remove());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_get_related_user_model_from_configuration()
|
||||
{
|
||||
$this->assertInstanceOf(User::class, $this->token->user()->getModel());
|
||||
}
|
||||
}
|
||||
|
||||
function config($key)
|
||||
{
|
||||
return [
|
||||
'keys' => [
|
||||
'foreign' => 'user_id',
|
||||
'owner' => 'id',
|
||||
],
|
||||
'model' => User::class,
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user