From 278b7ac52bf08e724ff4a14860f0be34ed3ae536 Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 16 Feb 2018 22:14:34 +0100 Subject: [PATCH] First tests for transformers. --- app/Transformers/AccountTransformer.php | 76 +++- database/factories/ModelFactory.php | 2 + .../V1/Controllers/AboutControllerTest.php | 88 ++++ .../V1/Controllers/AccountControllerTest.php | 78 ++++ tests/TestCase.php | 13 + .../Transformers/AccountTransformerTest.php | 399 ++++++++++++++++++ 6 files changed, 638 insertions(+), 18 deletions(-) create mode 100644 tests/Api/V1/Controllers/AboutControllerTest.php create mode 100644 tests/Api/V1/Controllers/AccountControllerTest.php create mode 100644 tests/Unit/Transformers/AccountTransformerTest.php diff --git a/app/Transformers/AccountTransformer.php b/app/Transformers/AccountTransformer.php index 49b7fbb3a9..a881a38585 100644 --- a/app/Transformers/AccountTransformer.php +++ b/app/Transformers/AccountTransformer.php @@ -30,6 +30,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\Note; use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; use Illuminate\Support\Collection; use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Item; @@ -57,7 +58,10 @@ class AccountTransformer extends TransformerAbstract protected $parameters; /** - * BillTransformer constructor. + * + * AccountTransformer constructor. + * + * @codeCoverageIgnore * * @param ParameterBag $parameters */ @@ -67,6 +71,26 @@ class AccountTransformer extends TransformerAbstract } /** + * Include piggy banks into end result. + * + * @codeCoverageIgnore + * + * @param Account $account + * + * @return FractalCollection + */ + public function includePiggyBanks(Account $account): FractalCollection + { + $piggies = $account->piggyBanks()->get(); + + return $this->collection($piggies, new PiggyBankTransformer($this->parameters), 'piggy_banks'); + } + + /** + * Include transactions into end result. + * + * @codeCoverageIgnore + * * @param Account $account * * @return FractalCollection @@ -94,18 +118,10 @@ class AccountTransformer extends TransformerAbstract } /** - * @param Account $account + * Include user data in end result. + * + * @codeCoverageIgnore * - * @return FractalCollection - */ - public function includePiggyBanks(Account $account): FractalCollection - { - $piggies = $account->piggyBanks()->get(); - - return $this->collection($piggies, new PiggyBankTransformer($this->parameters), 'piggy_banks'); - } - - /** * @param Account $account * * @return Item @@ -122,8 +138,9 @@ class AccountTransformer extends TransformerAbstract */ public function transform(Account $account): array { + $type = $account->accountType->type; $role = $account->getMeta('accountRole'); - if (strlen($role) === 0) { + if (strlen($role) === 0 || $type !== AccountType::ASSET) { $role = null; } $currencyId = (int)$account->getMeta('currency_id'); @@ -144,24 +161,44 @@ class AccountTransformer extends TransformerAbstract $currencyId = null; } + $monthlyPaymentDate = null; + $creditCardType = null; + if ($role === 'ccAsset' && $type === AccountType::ASSET) { + $creditCardType = $this->getMeta($account, 'ccType'); + $monthlyPaymentDate = $this->getMeta($account, 'ccMonthlyPaymentDate'); + } + + $openingBalance = null; + $openingBalanceDate = null; + if ($type === AccountType::ASSET) { + /** @var AccountRepositoryInterface $repository */ + $repository = app(AccountRepositoryInterface::class); + $repository->setuser($account->user); + $amount = $repository->getOpeningBalanceAmount($account); + $openingBalance = is_null($amount) ? null : round($amount, $decimalPlaces); + $openingBalanceDate = $repository->getOpeningBalanceDate($account); + } + $data = [ 'id' => (int)$account->id, 'updated_at' => $account->updated_at->toAtomString(), 'created_at' => $account->created_at->toAtomString(), 'name' => $account->name, 'active' => intval($account->active) === 1, - 'type' => $account->accountType->type, + 'type' => $type, 'currency_id' => $currencyId, 'currency_code' => $currencyCode, 'current_balance' => round(app('steam')->balance($account, $date), $decimalPlaces), 'current_balance_date' => $date->format('Y-m-d'), 'notes' => null, - 'monthly_payment_date' => $this->getMeta($account, 'ccMonthlyPaymentDate'), - 'credit_card_type' => $this->getMeta($account, 'ccType'), + 'monthly_payment_date' => $monthlyPaymentDate, + 'credit_card_type' => $creditCardType, 'account_number' => $this->getMeta($account, 'accountNumber'), 'iban' => $account->iban, 'bic' => $this->getMeta($account, 'BIC'), 'virtual_balance' => round($account->virtual_balance, $decimalPlaces), + 'opening_balance' => $openingBalance, + 'opening_balance_date' => $openingBalanceDate, 'role' => $role, 'links' => [ [ @@ -171,17 +208,20 @@ class AccountTransformer extends TransformerAbstract ], ]; - // todo opening balance /** @var Note $note */ $note = $account->notes()->first(); if (!is_null($note)) { - $data['notes'] = $note->text; + $data['notes'] = $note->text; // @codeCoverageIgnore } return $data; } /** + * Get meta data field for account. + * + * @codeCoverageIgnore + * * @param Account $account * @param string $field * diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index db84ef623b..687e06267b 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -227,6 +227,8 @@ $factory->define( function (Faker\Generator $faker) { return [ 'id' => $faker->unique()->numberBetween(1000, 10000), + 'created_at' => new Carbon, + 'updated_at' => new Carbon, 'name' => $faker->words(3, true), 'account_type_id' => 1, 'active' => true, diff --git a/tests/Api/V1/Controllers/AboutControllerTest.php b/tests/Api/V1/Controllers/AboutControllerTest.php new file mode 100644 index 0000000000..f1d8a58b9b --- /dev/null +++ b/tests/Api/V1/Controllers/AboutControllerTest.php @@ -0,0 +1,88 @@ +. + */ + +declare(strict_types=1); + +namespace Tests\Api\V1\Controllers; + +use FireflyIII\Transformers\UserTransformer; +use Laravel\Passport\Passport; +use Tests\TestCase; + +/** + * Class AboutControllerTest + * @runTestsInSeparateProcesses + * @preserveGlobalState disabled + */ +class AboutControllerTest extends TestCase +{ + /** @var array */ + protected $transformed + = [ + 'id' => 1, + 'email' => 'some@user', + 'links' => [ + 'rel' => 'self', + 'uri' => '/users/1', + ], + ]; + + public function setUp() + { + parent::setUp(); + Passport::actingAs($this->user()); + } + + /** + * @covers \FireflyIII\Api\V1\Controllers\AboutController::about + */ + public function testAbout() + { + // test API + $response = $this->get('/api/v1/about'); + $response->assertStatus(200); + $response->assertJson( + ['data' => [ + 'version' => true, + 'api_version' => true, + 'php_version' => true, + ]] + ); + } + + /** + * @covers \FireflyIII\Api\V1\Controllers\AboutController::user + */ + public function testUser() + { + // mock stuff: + $transformer = $this->overload(UserTransformer::class); + $transformer->shouldReceive('setCurrentScope')->andReturnSelf(); + $transformer->shouldReceive('transform')->andReturn($this->transformed); + + // test API + $response = $this->get('/api/v1/about/user'); + $response->assertStatus(200); + $response->assertJson(['data' => ['attributes' => true, 'links' => true]]); + } + + +} \ No newline at end of file diff --git a/tests/Api/V1/Controllers/AccountControllerTest.php b/tests/Api/V1/Controllers/AccountControllerTest.php new file mode 100644 index 0000000000..065684419c --- /dev/null +++ b/tests/Api/V1/Controllers/AccountControllerTest.php @@ -0,0 +1,78 @@ +. + */ + +declare(strict_types=1); + +namespace Tests\Api\V1\Controllers; + +use FireflyIII\Models\Account; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Transformers\AccountTransformer; +use Laravel\Passport\Passport; +use Tests\TestCase; + +/** + * Class AccountControllerTest + */ +class AccountControllerTest extends TestCase +{ + /** @var array */ + protected $transformed + = [ + 'id' => 1, + 'name' => 'Some account', + 'links' => [ + 'rel' => 'self', + 'uri' => '/accounts/1', + ], + ]; + + public function setUp() + { + parent::setUp(); + Passport::actingAs($this->user()); + } + + /** + * @covers \FireflyIII\Api\V1\Controllers\AccountController::index + */ + public function testIndex() + { + // mock stuff: + $repository = $this->mock(AccountRepositoryInterface::class); + $transformer = $this->overload(AccountTransformer::class); + $transformer->shouldReceive('setCurrentScope')->andReturnSelf(); + $transformer->shouldReceive('transform')->andReturn($this->transformed); + + $accounts = factory(Account::class, 10)->create(); + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('getAccountsByType')->withAnyArgs()->andReturn($accounts)->once(); + + $response = $this->get('/api/v1/accounts'); + $response->assertStatus(200); + $response->assertJson(['data' => []]); + $response->assertJson(['meta' => []]); + $response->assertJson(['links' => []]); + $response->assertSee('type=all'); // default returns this. + } + + +} \ No newline at end of file diff --git a/tests/TestCase.php b/tests/TestCase.php index 86b8f2ade6..e1548b0398 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -128,4 +128,17 @@ abstract class TestCase extends BaseTestCase return $object; } + + /** + * @param string $class + * + * @return Mockery\MockInterface + */ + protected function overload(string $class) + { + $externalMock = Mockery::mock('overload:' . $class); + + //$this->app->instance($class, $externalMock); + return $externalMock; + } } diff --git a/tests/Unit/Transformers/AccountTransformerTest.php b/tests/Unit/Transformers/AccountTransformerTest.php new file mode 100644 index 0000000000..7849dd7718 --- /dev/null +++ b/tests/Unit/Transformers/AccountTransformerTest.php @@ -0,0 +1,399 @@ +. + */ + +declare(strict_types=1); + +namespace Tests\Unit\Transformers; + +use Carbon\Carbon; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountMeta; +use FireflyIII\Models\Note; +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Transformers\AccountTransformer; +use Symfony\Component\HttpFoundation\ParameterBag; +use Tests\TestCase; + +/** + * Class AccountTransformerTest + */ +class AccountTransformerTest extends TestCase +{ + /** + * Basic account display. + * + * @covers \FireflyIII\Transformers\AccountTransformer::transform + */ + public function testBasic() + { + // make new account: + $account = Account::create( + [ + 'user_id' => $this->user()->id, + 'account_type_id' => 3, // asset account + 'name' => 'Random name #' . rand(1, 10000), + 'virtual_balance' => 12.34, + 'iban' => 'NL85ABNA0466812694', + 'active' => 1, + 'encrypted' => 0, + ] + ); + + $transformer = new AccountTransformer(new ParameterBag); + $result = $transformer->transform($account); + + $this->assertEquals($account->name, $result['name']); + $this->assertEquals('Asset account', $result['type']); + $this->assertEquals(12.34, $result['virtual_balance']); + $this->assertEquals(12.34, $result['current_balance']); + $this->assertNull($result['opening_balance']); + $this->assertNull($result['opening_balance_date']); + } + + /** + * Basic account display with custom date parameter. + * + * @covers \FireflyIII\Transformers\AccountTransformer::transform + */ + public function testBasicDate() + { + // make new account: + $account = Account::create( + [ + 'user_id' => $this->user()->id, + 'account_type_id' => 3, // asset account + 'name' => 'Random name #' . rand(1, 10000), + 'virtual_balance' => 12.34, + 'iban' => 'NL85ABNA0466812694', + 'active' => 1, + 'encrypted' => 0, + ] + ); + $parameterBag = new ParameterBag; + $parameterBag->set('date', new Carbon('2018-01-01')); + + $transformer = new AccountTransformer($parameterBag); + $result = $transformer->transform($account); + + $this->assertEquals($account->name, $result['name']); + $this->assertEquals('Asset account', $result['type']); + $this->assertEquals(12.34, $result['virtual_balance']); + $this->assertEquals(12.34, $result['current_balance']); + $this->assertEquals('2018-01-01', $result['current_balance_date']); + } + + /** + * Assert account has credit card meta data, should NOT be ignored in output. + * + * @covers \FireflyIII\Transformers\AccountTransformer::transform + */ + public function testCCDataAsset() + { + // make new account: + $account = Account::create( + [ + 'user_id' => $this->user()->id, + 'account_type_id' => 3, // asset account + 'name' => 'Random name #' . rand(1, 10000), + 'virtual_balance' => 12.34, + 'iban' => 'NL85ABNA0466812694', + 'active' => 1, + 'encrypted' => 0, + ] + ); + // add currency preference: + AccountMeta::create( + [ + 'account_id' => $account->id, + 'name' => 'currency_id', + 'data' => 1, // euro + ] + ); + + // add a note: + $note = Note::create( + [ + 'noteable_id' => $account->id, + 'noteable_type' => Account::class, + 'title' => null, + 'text' => 'I am a note #' . rand(1, 1000), + ] + ); + + // add credit card meta data (will be ignored) + AccountMeta::create( + [ + 'account_id' => $account->id, + 'name' => 'accountRole', + 'data' => 'ccAsset', + ] + ); + AccountMeta::create( + [ + 'account_id' => $account->id, + 'name' => 'ccMonthlyPaymentDate', + 'data' => '2018-02-01', + ] + ); + AccountMeta::create( + [ + 'account_id' => $account->id, + 'name' => 'ccType', + 'data' => 'monthlyFull', + ] + ); + + + $transformer = new AccountTransformer(new ParameterBag); + $result = $transformer->transform($account); + + $this->assertEquals($account->name, $result['name']); + $this->assertEquals('Asset account', $result['type']); + $this->assertEquals(12.34, $result['virtual_balance']); + $this->assertEquals(12.34, $result['current_balance']); + $this->assertEquals(1, $result['currency_id']); + $this->assertEquals('EUR', $result['currency_code']); + $this->assertEquals($note->text, $result['notes']); + $this->assertEquals('2018-02-01', $result['monthly_payment_date']); + $this->assertEquals('monthlyFull', $result['credit_card_type']); + $this->assertEquals('ccAsset', $result['role']); + } + + /** + * Expense account has credit card meta data, should be ignored in output. + * + * @covers \FireflyIII\Transformers\AccountTransformer::transform + */ + public function testIgnoreCCExpense() + { + // make new account: + $account = Account::create( + [ + 'user_id' => $this->user()->id, + 'account_type_id' => 4, // expense account + 'name' => 'Random name #' . rand(1, 10000), + 'virtual_balance' => 12.34, + 'iban' => 'NL85ABNA0466812694', + 'active' => 1, + 'encrypted' => 0, + ] + ); + // add currency preference: + AccountMeta::create( + [ + 'account_id' => $account->id, + 'name' => 'currency_id', + 'data' => 1, // euro + ] + ); + + // add a note: + $note = Note::create( + [ + 'noteable_id' => $account->id, + 'noteable_type' => Account::class, + 'title' => null, + 'text' => 'I am a note #' . rand(1, 1000), + ] + ); + + // add credit card meta data (will be ignored) + AccountMeta::create( + [ + 'account_id' => $account->id, + 'name' => 'accountRole', + 'data' => 'ccAsset', + ] + ); + AccountMeta::create( + [ + 'account_id' => $account->id, + 'name' => 'ccMonthlyPaymentDate', + 'data' => '2018-02-01', + ] + ); + AccountMeta::create( + [ + 'account_id' => $account->id, + 'name' => 'ccType', + 'data' => 'monthlyFull', + ] + ); + + + $transformer = new AccountTransformer(new ParameterBag); + $result = $transformer->transform($account); + + $this->assertEquals($account->name, $result['name']); + $this->assertEquals('Expense account', $result['type']); + $this->assertEquals(12.34, $result['virtual_balance']); + $this->assertEquals(12.34, $result['current_balance']); + $this->assertEquals(1, $result['currency_id']); + $this->assertEquals('EUR', $result['currency_code']); + $this->assertEquals($note->text, $result['notes']); + $this->assertNull($result['monthly_payment_date']); + $this->assertNull($result['credit_card_type']); + $this->assertNull($result['role']); + } + + /** + * Basic account display. + * + * @covers \FireflyIII\Transformers\AccountTransformer::transform + */ + public function testOpeningBalance() + { + // make new account: + $account = Account::create( + [ + 'user_id' => $this->user()->id, + 'account_type_id' => 3, // asset account + 'name' => 'Random name #' . rand(1, 10000), + 'virtual_balance' => 12.34, + 'iban' => 'NL85ABNA0466812694', + 'active' => 1, + 'encrypted' => 0, + ] + ); + + // create opening balance: + $journal = TransactionJournal::create( + [ + 'user_id' => $this->user()->id, + 'transaction_type_id' => 4, // opening balance + 'transaction_currency_id' => 1, // EUR + 'description' => 'Opening', + 'date' => '2018-01-01', + 'completed' => 1, + ] + ); + $transaction = Transaction::create( + [ + 'account_id' => $account->id, + 'transaction_journal_id' => $journal->id, + 'transaction_currency_id' => 1, + 'amount' => '45.67', + ] + ); + + $transformer = new AccountTransformer(new ParameterBag); + $result = $transformer->transform($account); + + $this->assertEquals($account->name, $result['name']); + $this->assertEquals('Asset account', $result['type']); + $this->assertEquals(12.34, $result['virtual_balance']); + $this->assertEquals(58.01, $result['current_balance']); // add opening balance. + $this->assertEquals(45.67, $result['opening_balance']); + $this->assertEquals('2018-01-01', $result['opening_balance_date']); + } + + /** + * Account has currency preference, should be reflected in output. + * + * @covers \FireflyIII\Transformers\AccountTransformer::transform + */ + public function testWithCurrency() + { + // make new account: + $account = Account::create( + [ + 'user_id' => $this->user()->id, + 'account_type_id' => 3, // asset account + 'name' => 'Random name #' . rand(1, 10000), + 'virtual_balance' => 12.34, + 'iban' => 'NL85ABNA0466812694', + 'active' => 1, + 'encrypted' => 0, + ] + ); + // add currency preference: + AccountMeta::create( + [ + 'account_id' => $account->id, + 'name' => 'currency_id', + 'data' => 1, // euro + ] + ); + + $transformer = new AccountTransformer(new ParameterBag); + $result = $transformer->transform($account); + + $this->assertEquals($account->name, $result['name']); + $this->assertEquals('Asset account', $result['type']); + $this->assertEquals(12.34, $result['virtual_balance']); + $this->assertEquals(12.34, $result['current_balance']); + $this->assertEquals(1, $result['currency_id']); + $this->assertEquals('EUR', $result['currency_code']); + } + + /** + * Account has notes, should be reflected in output. + * + * @covers \FireflyIII\Transformers\AccountTransformer::transform + */ + public function testWithNotes() + { + // make new account: + $account = Account::create( + [ + 'user_id' => $this->user()->id, + 'account_type_id' => 3, // asset account + 'name' => 'Random name #' . rand(1, 10000), + 'virtual_balance' => 12.34, + 'iban' => 'NL85ABNA0466812694', + 'active' => 1, + 'encrypted' => 0, + ] + ); + // add currency preference: + AccountMeta::create( + [ + 'account_id' => $account->id, + 'name' => 'currency_id', + 'data' => 1, // euro + ] + ); + + // add a note: + $note = Note::create( + [ + 'noteable_id' => $account->id, + 'noteable_type' => Account::class, + 'title' => null, + 'text' => 'I am a note #' . rand(1, 1000), + ] + ); + + $transformer = new AccountTransformer(new ParameterBag); + $result = $transformer->transform($account); + + $this->assertEquals($account->name, $result['name']); + $this->assertEquals('Asset account', $result['type']); + $this->assertEquals(12.34, $result['virtual_balance']); + $this->assertEquals(12.34, $result['current_balance']); + $this->assertEquals(1, $result['currency_id']); + $this->assertEquals('EUR', $result['currency_code']); + $this->assertEquals($note->text, $result['notes']); + } + + +} \ No newline at end of file