diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index 1f0f162558..b478e3ee61 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -13,14 +13,13 @@ declare(strict_types = 1); namespace FireflyIII\Http\Controllers\Auth; use FireflyIII\Http\Controllers\Controller; +use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\User; use Illuminate\Foundation\Auth\SendsPasswordResetEmails; use Illuminate\Http\Request; use Password; /** - * @codeCoverageIgnore - * * Class ForgotPasswordController * * @package FireflyIII\Http\Controllers\Auth @@ -46,21 +45,18 @@ class ForgotPasswordController extends Controller * * @return \Illuminate\Http\RedirectResponse */ - public function sendResetLinkEmail(Request $request) + public function sendResetLinkEmail(Request $request, UserRepositoryInterface $repository) { $this->validate($request, ['email' => 'required|email']); // verify if the user is not a demo user. If so, we give him back an error. $user = User::where('email', $request->get('email'))->first(); - if (!is_null($user) && $user->hasRole('demo')) { - return back()->withErrors( - ['email' => trans('firefly.cannot_reset_demo_user')] - ); + + if (!is_null($user) && $repository->hasRole($user, 'demo')) { + return back()->withErrors(['email' => trans('firefly.cannot_reset_demo_user')]); } - $response = $this->broker()->sendResetLink( - $request->only('email') - ); + $response = $this->broker()->sendResetLink($request->only('email')); if ($response === Password::RESET_LINK_SENT) { return back()->with('status', trans($response)); @@ -69,8 +65,6 @@ class ForgotPasswordController extends Controller // If an error was returned by the password broker, we will get this message // translated so we can notify a user of the problem. We'll redirect back // to where the users came from so they can attempt this process again. - return back()->withErrors( - ['email' => trans($response)] - ); + return back()->withErrors(['email' => trans($response)]); // @codeCoverageIgnore } } diff --git a/app/Http/Controllers/Auth/TwoFactorController.php b/app/Http/Controllers/Auth/TwoFactorController.php index 55f581c777..337f9391fd 100644 --- a/app/Http/Controllers/Auth/TwoFactorController.php +++ b/app/Http/Controllers/Auth/TwoFactorController.php @@ -41,11 +41,12 @@ class TwoFactorController extends Controller $user = auth()->user(); // to make sure the validator in the next step gets the secret, we push it in session - $secret = Preferences::get('twoFactorAuthSecret', null)->data; + $secretPreference = Preferences::get('twoFactorAuthSecret', null); + $secret = is_null($secretPreference) ? null : $secretPreference->data; $title = strval(trans('firefly.two_factor_title')); // make sure the user has two factor configured: - $has2FA = Preferences::get('twoFactorAuthEnabled', null)->data; + $has2FA = Preferences::get('twoFactorAuthEnabled', false)->data; if (is_null($has2FA) || $has2FA === false) { return redirect(route('index')); } diff --git a/app/Http/Controllers/Chart/AccountController.php b/app/Http/Controllers/Chart/AccountController.php index 1f22e7f32d..6fb04e613c 100644 --- a/app/Http/Controllers/Chart/AccountController.php +++ b/app/Http/Controllers/Chart/AccountController.php @@ -497,8 +497,6 @@ class AccountController extends Controller $cache->addProperty('chart.account.account-balance-chart'); $cache->addProperty($accounts); if ($cache->has()) { - Log::debug('Return chart.account.account-balance-chart from cache.'); - return $cache->get(); // @codeCoverageIgnore } Log::debug('Regenerate chart.account.account-balance-chart from scratch.'); diff --git a/app/Http/Controllers/Chart/BudgetReportController.php b/app/Http/Controllers/Chart/BudgetReportController.php index 3c3b2a9a36..71930dd59a 100644 --- a/app/Http/Controllers/Chart/BudgetReportController.php +++ b/app/Http/Controllers/Chart/BudgetReportController.php @@ -9,7 +9,7 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; @@ -24,7 +24,6 @@ use FireflyIII\Models\Budget; use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Support\CacheProperties; use Illuminate\Support\Collection; @@ -41,8 +40,6 @@ use Response; class BudgetReportController extends Controller { - /** @var AccountRepositoryInterface */ - private $accountRepository; /** @var BudgetRepositoryInterface */ private $budgetRepository; /** @var GeneratorInterface */ @@ -56,9 +53,8 @@ class BudgetReportController extends Controller parent::__construct(); $this->middleware( function ($request, $next) { - $this->generator = app(GeneratorInterface::class); - $this->budgetRepository = app(BudgetRepositoryInterface::class); - $this->accountRepository = app(AccountRepositoryInterface::class); + $this->generator = app(GeneratorInterface::class); + $this->budgetRepository = app(BudgetRepositoryInterface::class); return $next($request); } @@ -133,8 +129,6 @@ class BudgetReportController extends Controller if ($cache->has()) { return Response::json($cache->get()); // @codeCoverageIgnore } - /** @var BudgetRepositoryInterface $repository */ - $repository = app(BudgetRepositoryInterface::class); $format = Navigation::preferredCarbonLocalizedFormat($start, $end); $function = Navigation::preferredEndOfPeriod($start, $end); $chartData = []; @@ -163,7 +157,7 @@ class BudgetReportController extends Controller 'entries' => [], ]; } - $allBudgetLimits = $repository->getAllBudgetLimits($start, $end); + $allBudgetLimits = $this->budgetRepository->getAllBudgetLimits($start, $end); $sumOfExpenses = []; $leftOfLimits = []; while ($currentStart < $end) { diff --git a/app/Http/Controllers/Chart/CategoryReportController.php b/app/Http/Controllers/Chart/CategoryReportController.php index 7703725bfe..5f8b21c210 100644 --- a/app/Http/Controllers/Chart/CategoryReportController.php +++ b/app/Http/Controllers/Chart/CategoryReportController.php @@ -9,7 +9,7 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; @@ -23,8 +23,6 @@ use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Category; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Support\CacheProperties; use Illuminate\Support\Collection; use Navigation; @@ -41,10 +39,6 @@ use Response; class CategoryReportController extends Controller { - /** @var AccountRepositoryInterface */ - private $accountRepository; - /** @var CategoryRepositoryInterface */ - private $categoryRepository; /** @var GeneratorInterface */ private $generator; @@ -56,9 +50,7 @@ class CategoryReportController extends Controller parent::__construct(); $this->middleware( function ($request, $next) { - $this->generator = app(GeneratorInterface::class); - $this->categoryRepository = app(CategoryRepositoryInterface::class); - $this->accountRepository = app(AccountRepositoryInterface::class); + $this->generator = app(GeneratorInterface::class); return $next($request); } diff --git a/app/Validation/FireflyValidator.php b/app/Validation/FireflyValidator.php index b4f4ee4e19..cf4b60c3f9 100644 --- a/app/Validation/FireflyValidator.php +++ b/app/Validation/FireflyValidator.php @@ -29,7 +29,6 @@ use Google2FA; use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Contracts\Translation\Translator; use Illuminate\Validation\Validator; -use Session; /** * Class FireflyValidator @@ -66,7 +65,7 @@ class FireflyValidator extends Validator return false; } - $secret = Session::get('two-factor-secret'); + $secret = session('two-factor-secret'); return Google2FA::verifyKey($secret, $value); } diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index 453d10608f..a0d1e7c2b7 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -8,7 +8,10 @@ * * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); + +use Carbon\Carbon; + /* |-------------------------------------------------------------------------- @@ -182,6 +185,7 @@ $factory->define( 'description' => $faker->words(3, true), 'source_account_name' => $faker->words(3, true), 'destination_account_id' => $faker->numberBetween(1, 10), + 'date' => new Carbon, 'destination_account_name' => $faker->words(3, true), 'amount' => strval($faker->randomFloat(2, -100, 100)), 'budget_id' => 0, diff --git a/database/migrations/2016_06_16_000000_create_support_tables.php b/database/migrations/2016_06_16_000000_create_support_tables.php index 6d0234802c..cd16910972 100644 --- a/database/migrations/2016_06_16_000000_create_support_tables.php +++ b/database/migrations/2016_06_16_000000_create_support_tables.php @@ -8,7 +8,7 @@ * * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; @@ -76,6 +76,23 @@ class CreateSupportTables extends Migration } } + private function createConfigurationTable() + { + if (!Schema::hasTable('configuration')) { + Schema::create( + 'configuration', function (Blueprint $table) { + + $table->increments('id'); + $table->timestamps(); + $table->softDeletes(); + $table->string('name', 50); + $table->text('data'); + $table->unique(['name']); + } + ); + } + } + /** * */ @@ -99,23 +116,6 @@ class CreateSupportTables extends Migration } } - private function createConfigurationTable() - { - if (!Schema::hasTable('configuration')) { - Schema::create( - 'configuration', function (Blueprint $table) { - - $table->increments('id'); - $table->timestamps(); - $table->softDeletes(); - $table->string('name', 50); - $table->text('data'); - $table->unique(['name']); - } - ); - } - } - /** * */ diff --git a/database/migrations/2016_06_16_000001_create_users_table.php b/database/migrations/2016_06_16_000001_create_users_table.php index 0120a485ed..563fbd1584 100644 --- a/database/migrations/2016_06_16_000001_create_users_table.php +++ b/database/migrations/2016_06_16_000001_create_users_table.php @@ -8,7 +8,7 @@ * * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; @@ -18,6 +18,14 @@ use Illuminate\Database\Schema\Blueprint; */ class CreateUsersTable extends Migration { + /** + * Reverse the migrations. + */ + public function down() + { + Schema::drop('users'); + } + /** * Run the migrations. * @@ -40,12 +48,4 @@ class CreateUsersTable extends Migration ); } } - - /** - * Reverse the migrations. - */ - public function down() - { - Schema::drop('users'); - } } diff --git a/database/migrations/2016_06_16_000002_create_main_tables.php b/database/migrations/2016_06_16_000002_create_main_tables.php index 1090bcb05f..0f5fe8d4e4 100644 --- a/database/migrations/2016_06_16_000002_create_main_tables.php +++ b/database/migrations/2016_06_16_000002_create_main_tables.php @@ -8,7 +8,7 @@ * * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; diff --git a/database/migrations/2016_08_25_091522_changes_for_3101.php b/database/migrations/2016_08_25_091522_changes_for_3101.php index 9d0e38a548..b317ef163c 100644 --- a/database/migrations/2016_08_25_091522_changes_for_3101.php +++ b/database/migrations/2016_08_25_091522_changes_for_3101.php @@ -8,7 +8,7 @@ * * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; diff --git a/database/migrations/2016_09_12_121359_fix_nullables.php b/database/migrations/2016_09_12_121359_fix_nullables.php index 54033eac70..ba037d328b 100644 --- a/database/migrations/2016_09_12_121359_fix_nullables.php +++ b/database/migrations/2016_09_12_121359_fix_nullables.php @@ -8,7 +8,7 @@ * * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; diff --git a/database/migrations/2016_12_28_203205_changes_for_v431.php b/database/migrations/2016_12_28_203205_changes_for_v431.php index 310ccac5a8..8b1ae14c79 100644 --- a/database/migrations/2016_12_28_203205_changes_for_v431.php +++ b/database/migrations/2016_12_28_203205_changes_for_v431.php @@ -43,11 +43,11 @@ class ChangesForV431 extends Migration ); // change field "start_date" to "startdate" -// Schema::table( -// 'budget_limits', function (Blueprint $table) { -// $table->renameColumn('startdate', 'start_date'); -// } -// ); + // Schema::table( + // 'budget_limits', function (Blueprint $table) { + // $table->renameColumn('startdate', 'start_date'); + // } + // ); } diff --git a/database/seeds/AccountTypeSeeder.php b/database/seeds/AccountTypeSeeder.php index 8f8690f33a..e98b6b8db7 100644 --- a/database/seeds/AccountTypeSeeder.php +++ b/database/seeds/AccountTypeSeeder.php @@ -9,7 +9,7 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); use FireflyIII\Models\AccountType; use Illuminate\Database\Seeder; diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php index a92b556f6a..504c129e47 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -8,7 +8,7 @@ * * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); use Illuminate\Database\Seeder; diff --git a/database/seeds/PermissionSeeder.php b/database/seeds/PermissionSeeder.php index 2916470354..94b3e48afa 100644 --- a/database/seeds/PermissionSeeder.php +++ b/database/seeds/PermissionSeeder.php @@ -9,8 +9,7 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); - +declare(strict_types=1); use FireflyIII\Models\Role; @@ -29,10 +28,10 @@ class PermissionSeeder extends Seeder $owner->description = 'User runs this instance of FF3'; // optional $owner->save(); - $demo = new Role; - $demo->name ='demo'; + $demo = new Role; + $demo->name = 'demo'; $demo->display_name = 'Demo User'; - $demo->description = 'User is a demo user'; + $demo->description = 'User is a demo user'; $demo->save(); } diff --git a/database/seeds/TransactionCurrencySeeder.php b/database/seeds/TransactionCurrencySeeder.php index 5d8fe07845..8f51c69cd1 100644 --- a/database/seeds/TransactionCurrencySeeder.php +++ b/database/seeds/TransactionCurrencySeeder.php @@ -9,7 +9,7 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); use FireflyIII\Models\TransactionCurrency; use Illuminate\Database\Seeder; diff --git a/database/seeds/TransactionTypeSeeder.php b/database/seeds/TransactionTypeSeeder.php index 06ff214776..6c1a709bb3 100644 --- a/database/seeds/TransactionTypeSeeder.php +++ b/database/seeds/TransactionTypeSeeder.php @@ -9,7 +9,7 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); use FireflyIII\Models\TransactionType; use Illuminate\Database\Seeder; diff --git a/routes/web.php b/routes/web.php index 7f407cf1d2..0806fc6600 100755 --- a/routes/web.php +++ b/routes/web.php @@ -28,7 +28,7 @@ Route::group( // Password Reset Routes... Route::get('password/reset/{token}', ['uses' => 'Auth\ResetPasswordController@showResetForm', 'as' => 'password.reset']); - Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail'); + Route::post('password/email', ['uses' => 'Auth\ForgotPasswordController@sendResetLinkEmail','as' => 'password.email']); Route::post('password/reset', 'Auth\ResetPasswordController@reset'); Route::get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm'); @@ -50,7 +50,6 @@ Route::group( /** * For the two factor routes, the user must be logged in, but NOT 2FA. Account confirmation does not matter here. * - * @deprecated */ Route::group( ['middleware' => 'user-logged-in-no-2fa', 'prefix' => 'two-factor', 'as' => 'two-factor.', 'namespace' => 'Auth'], function () { diff --git a/tests/Feature/Controllers/Auth/ForgotPasswordControllerTest.php b/tests/Feature/Controllers/Auth/ForgotPasswordControllerTest.php new file mode 100644 index 0000000000..34e1d7e36a --- /dev/null +++ b/tests/Feature/Controllers/Auth/ForgotPasswordControllerTest.php @@ -0,0 +1,51 @@ +mock(UserRepositoryInterface::class); + $repository->shouldReceive('hasRole')->andReturn(false); + $data = [ + 'email' => 'thegrumpydictator@gmail.com', + ]; + + $response = $this->post(route('password.email'), $data); + $response->assertStatus(302); + } + + /** + * @covers \FireflyIII\Http\Controllers\Auth\ForgotPasswordController::__construct + * @covers \FireflyIII\Http\Controllers\Auth\ForgotPasswordController::sendResetLinkEmail + */ + public function testSendResetLinkEmailDemo() + { + $repository = $this->mock(UserRepositoryInterface::class); + $repository->shouldReceive('hasRole')->andReturn(true); + $data = [ + 'email' => 'thegrumpydictator@gmail.com', + ]; + + $response = $this->post(route('password.email'), $data); + $response->assertStatus(302); + } +} \ No newline at end of file diff --git a/tests/Feature/Controllers/Auth/TwoFactorControllerTest.php b/tests/Feature/Controllers/Auth/TwoFactorControllerTest.php index b1882647e2..ef7731b512 100644 --- a/tests/Feature/Controllers/Auth/TwoFactorControllerTest.php +++ b/tests/Feature/Controllers/Auth/TwoFactorControllerTest.php @@ -7,12 +7,13 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); namespace Tests\Feature\Controllers\Auth; use FireflyIII\Models\Preference; +use PragmaRX\Google2FA\Contracts\Google2FA; use Preferences; use Tests\TestCase; @@ -30,17 +31,53 @@ class TwoFactorControllerTest extends TestCase { $this->be($this->user()); - $falsePreference = new Preference; - $falsePreference->data = true; + $truePref = new Preference; + $truePref->data = true; $secretPreference = new Preference; $secretPreference->data = 'BlablaSeecret'; - Preferences::shouldReceive('get')->withArgs(['twoFactorAuthEnabled', false])->andReturn($falsePreference); - Preferences::shouldReceive('get')->withArgs(['twoFactorAuthSecret', null])->andReturn($secretPreference); - Preferences::shouldReceive('get')->withArgs(['twoFactorAuthSecret'])->andReturn($secretPreference); + Preferences::shouldReceive('get')->withArgs(['twoFactorAuthEnabled', false])->andReturn($truePref)->twice(); + Preferences::shouldReceive('get')->withArgs(['twoFactorAuthSecret', null])->andReturn($secretPreference)->once(); + Preferences::shouldReceive('get')->withArgs(['twoFactorAuthSecret'])->andReturn($secretPreference)->once(); $response = $this->get(route('two-factor.index')); $response->assertStatus(200); } + /** + * @covers \FireflyIII\Http\Controllers\Auth\TwoFactorController::index + */ + public function testIndexNo2FA() + { + $this->be($this->user()); + + $falsePreference = new Preference; + $falsePreference->data = false; + Preferences::shouldReceive('get')->withArgs(['twoFactorAuthEnabled', false])->andReturn($falsePreference)->twice(); + Preferences::shouldReceive('get')->withArgs(['twoFactorAuthSecret', null])->andReturn(null)->once(); + Preferences::shouldReceive('get')->withArgs(['twoFactorAuthSecret'])->andReturn(null)->once(); + $response = $this->get(route('two-factor.index')); + $response->assertStatus(302); + $response->assertRedirect(route('index')); + } + + /** + * @covers \FireflyIII\Http\Controllers\Auth\TwoFactorController::index + * @expectedExceptionMessage Your two factor authentication secret is empty + */ + public function testIndexNoSecret() + { + $this->be($this->user()); + + $truePref = new Preference; + $truePref->data = true; + $secretPreference = new Preference; + $secretPreference->data = ''; + Preferences::shouldReceive('get')->withArgs(['twoFactorAuthEnabled', false])->andReturn($truePref)->twice(); + Preferences::shouldReceive('get')->withArgs(['twoFactorAuthSecret', null])->andReturn($secretPreference)->once(); + Preferences::shouldReceive('get')->withArgs(['twoFactorAuthSecret'])->andReturn($secretPreference)->once(); + $response = $this->get(route('two-factor.index')); + $response->assertStatus(500); + } + /** * @covers \FireflyIII\Http\Controllers\Auth\TwoFactorController::lostTwoFactor */ @@ -59,4 +96,18 @@ class TwoFactorControllerTest extends TestCase $response->assertStatus(200); } + /** + * @covers \FireflyIII\Http\Controllers\Auth\TwoFactorController::postIndex + */ + public function testPostIndex() + { + $data = ['code' => '123456']; + $google = $this->mock(Google2FA::class); + $google->shouldReceive('verifyKey')->andReturn(true)->once(); + + $this->be($this->user()); + $response = $this->post(route('two-factor.post'), $data); + $response->assertStatus(302); + } + } diff --git a/tests/Feature/Controllers/Chart/AccountControllerTest.php b/tests/Feature/Controllers/Chart/AccountControllerTest.php index b172f22278..21665bcc27 100644 --- a/tests/Feature/Controllers/Chart/AccountControllerTest.php +++ b/tests/Feature/Controllers/Chart/AccountControllerTest.php @@ -7,7 +7,7 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); namespace Tests\Feature\Controllers\Chart; @@ -15,12 +15,16 @@ namespace Tests\Feature\Controllers\Chart; use Carbon\Carbon; use FireflyIII\Generator\Chart\Basic\GeneratorInterface; use FireflyIII\Helpers\Collector\JournalCollectorInterface; +use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; +use FireflyIII\Models\Category; +use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use Illuminate\Support\Collection; +use Preferences; use Steam; use Tests\TestCase; @@ -58,10 +62,11 @@ class AccountControllerTest extends TestCase */ public function testExpenseAccounts(string $range) { + $account = factory(Account::class)->make(); $generator = $this->mock(GeneratorInterface::class); $accountRepos = $this->mock(AccountRepositoryInterface::class); - $accountRepos->shouldReceive('getAccountsByType')->withArgs([[AccountType::EXPENSE, AccountType::BENEFICIARY]])->andReturn(new Collection); + $accountRepos->shouldReceive('getAccountsByType')->withArgs([[AccountType::EXPENSE, AccountType::BENEFICIARY]])->andReturn(new Collection([$account])); $generator->shouldReceive('singleSet')->andReturn([]); Steam::shouldReceive('balancesById')->twice()->andReturn([]); @@ -84,12 +89,13 @@ class AccountControllerTest extends TestCase $generator = $this->mock(GeneratorInterface::class); $collector = $this->mock(JournalCollectorInterface::class); $budgetRepos = $this->mock(BudgetRepositoryInterface::class); + $transaction = factory(Transaction::class)->make(); $collector->shouldReceive('setAccounts')->andReturnSelf(); $collector->shouldReceive('setRange')->andReturnSelf(); $collector->shouldReceive('withBudgetInformation')->andReturnSelf(); $collector->shouldReceive('setTypes')->withArgs([[TransactionType::WITHDRAWAL]])->andReturnSelf(); - $collector->shouldReceive('getJournals')->andReturn(new Collection); + $collector->shouldReceive('getJournals')->andReturn(new Collection([$transaction])); $generator->shouldReceive('pieChart')->andReturn([]); $budgetRepos->shouldReceive('getBudgets')->andReturn(new Collection); @@ -100,14 +106,48 @@ class AccountControllerTest extends TestCase $response->assertStatus(200); } + /** + * @covers \FireflyIII\Http\Controllers\Chart\AccountController::expenseBudgetAll + * @covers \FireflyIII\Http\Controllers\Chart\AccountController::getBudgetNames + * @dataProvider dateRangeProvider + * + * @param string $range + */ + public function testExpenseBudgetAll(string $range) + { + $generator = $this->mock(GeneratorInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $budgetRepos = $this->mock(BudgetRepositoryInterface::class); + $accountRepos = $this->mock(AccountRepositoryInterface::class); + $transaction = factory(Transaction::class)->make(); + + $collector->shouldReceive('setAccounts')->andReturnSelf(); + $collector->shouldReceive('setRange')->andReturnSelf(); + $collector->shouldReceive('withBudgetInformation')->andReturnSelf(); + $collector->shouldReceive('setTypes')->withArgs([[TransactionType::WITHDRAWAL]])->andReturnSelf(); + $collector->shouldReceive('getJournals')->andReturn(new Collection([$transaction])); + $generator->shouldReceive('pieChart')->andReturn([]); + $budgetRepos->shouldReceive('getBudgets')->andReturn(new Collection); + $accountRepos->shouldReceive('oldestJournalDate')->andReturn(Carbon::createFromTimestamp(time())->startOfMonth()); + + + $this->be($this->user()); + $this->changeDateRange($this->user(), $range); + $response = $this->get(route('chart.account.expense-budget-all', [1])); + $response->assertStatus(200); + } + /** * @covers \FireflyIII\Http\Controllers\Chart\AccountController::expenseCategory + * @covers \FireflyIII\Http\Controllers\Chart\AccountController::getCategoryNames * @dataProvider dateRangeProvider * * @param string $range */ public function testExpenseCategory(string $range) { + $transaction = factory(Transaction::class)->make(); + $category = factory(Category::class)->make(); $generator = $this->mock(GeneratorInterface::class); $collector = $this->mock(JournalCollectorInterface::class); $categoryRepos = $this->mock(CategoryRepositoryInterface::class); @@ -116,9 +156,9 @@ class AccountControllerTest extends TestCase $collector->shouldReceive('setRange')->andReturnSelf(); $collector->shouldReceive('withCategoryInformation')->andReturnSelf(); $collector->shouldReceive('setTypes')->withArgs([[TransactionType::WITHDRAWAL]])->andReturnSelf(); - $collector->shouldReceive('getJournals')->andReturn(new Collection); + $collector->shouldReceive('getJournals')->andReturn(new Collection([$transaction])); $generator->shouldReceive('pieChart')->andReturn([]); - $categoryRepos->shouldReceive('getCategories')->andReturn(new Collection); + $categoryRepos->shouldReceive('getCategories')->andReturn(new Collection([$category])); $this->be($this->user()); $this->changeDateRange($this->user(), $range); @@ -126,6 +166,37 @@ class AccountControllerTest extends TestCase $response->assertStatus(200); } + /** + * @covers \FireflyIII\Http\Controllers\Chart\AccountController::expenseCategoryAll + * @covers \FireflyIII\Http\Controllers\Chart\AccountController::getCategoryNames + * @dataProvider dateRangeProvider + * + * @param string $range + */ + public function testExpenseCategoryAll(string $range) + { + $transaction = factory(Transaction::class)->make(); + $category = factory(Category::class)->make(); + $generator = $this->mock(GeneratorInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $categoryRepos = $this->mock(CategoryRepositoryInterface::class); + $accountRepos = $this->mock(AccountRepositoryInterface::class); + + $collector->shouldReceive('setAccounts')->andReturnSelf(); + $collector->shouldReceive('setRange')->andReturnSelf(); + $collector->shouldReceive('withCategoryInformation')->andReturnSelf(); + $collector->shouldReceive('setTypes')->withArgs([[TransactionType::WITHDRAWAL]])->andReturnSelf(); + $collector->shouldReceive('getJournals')->andReturn(new Collection([$transaction])); + $generator->shouldReceive('pieChart')->andReturn([]); + $categoryRepos->shouldReceive('getCategories')->andReturn(new Collection([$category])); + $accountRepos->shouldReceive('oldestJournalDate')->andReturn(Carbon::createFromTimestamp(time())->startOfMonth()); + + $this->be($this->user()); + $this->changeDateRange($this->user(), $range); + $response = $this->get(route('chart.account.expense-category-all', [1])); + $response->assertStatus(200); + } + /** * @covers \FireflyIII\Http\Controllers\Chart\AccountController::frontpage * @covers \FireflyIII\Http\Controllers\Chart\AccountController::__construct @@ -140,6 +211,9 @@ class AccountControllerTest extends TestCase $generator = $this->mock(GeneratorInterface::class); $accountRepos = $this->mock(AccountRepositoryInterface::class); + // change the preference: + Preferences::setForUser($this->user(), 'frontPageAccounts', []); + $accountRepos->shouldReceive('getAccountsByType')->withArgs([[AccountType::DEFAULT, AccountType::ASSET]])->andReturn(new Collection); $accountRepos->shouldReceive('getAccountsById')->andReturn(new Collection); Steam::shouldReceive('balanceInRange')->andReturn([]); @@ -159,6 +233,8 @@ class AccountControllerTest extends TestCase */ public function testIncomeCategory(string $range) { + $transaction = factory(Transaction::class)->make(); + $account = factory(Account::class)->make(); $generator = $this->mock(GeneratorInterface::class); $collector = $this->mock(JournalCollectorInterface::class); $categoryRepos = $this->mock(CategoryRepositoryInterface::class); @@ -167,9 +243,9 @@ class AccountControllerTest extends TestCase $collector->shouldReceive('setRange')->andReturnSelf(); $collector->shouldReceive('withCategoryInformation')->andReturnSelf(); $collector->shouldReceive('setTypes')->withArgs([[TransactionType::DEPOSIT]])->andReturnSelf(); - $collector->shouldReceive('getJournals')->andReturn(new Collection); + $collector->shouldReceive('getJournals')->andReturn(new Collection([$transaction])); $generator->shouldReceive('pieChart')->andReturn([]); - $categoryRepos->shouldReceive('getCategories')->andReturn(new Collection); + $categoryRepos->shouldReceive('getCategories')->andReturn(new Collection([$account])); $this->be($this->user()); $this->changeDateRange($this->user(), $range); @@ -177,6 +253,36 @@ class AccountControllerTest extends TestCase $response->assertStatus(200); } + /** + * @covers \FireflyIII\Http\Controllers\Chart\AccountController::incomeCategoryAll + * @dataProvider dateRangeProvider + * + * @param string $range + */ + public function testIncomeCategoryAll(string $range) + { + $transaction = factory(Transaction::class)->make(); + $account = factory(Account::class)->make(); + $generator = $this->mock(GeneratorInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $categoryRepos = $this->mock(CategoryRepositoryInterface::class); + $accountRepos = $this->mock(AccountRepositoryInterface::class); + + $collector->shouldReceive('setAccounts')->andReturnSelf(); + $collector->shouldReceive('setRange')->andReturnSelf(); + $collector->shouldReceive('withCategoryInformation')->andReturnSelf(); + $collector->shouldReceive('setTypes')->withArgs([[TransactionType::DEPOSIT]])->andReturnSelf(); + $collector->shouldReceive('getJournals')->andReturn(new Collection([$transaction])); + $generator->shouldReceive('pieChart')->andReturn([]); + $categoryRepos->shouldReceive('getCategories')->andReturn(new Collection([$account])); + $accountRepos->shouldReceive('oldestJournalDate')->andReturn(Carbon::createFromTimestamp(time())->startOfMonth()); + + $this->be($this->user()); + $this->changeDateRange($this->user(), $range); + $response = $this->get(route('chart.account.income-category-all', [1])); + $response->assertStatus(200); + } + /** * @covers \FireflyIII\Http\Controllers\Chart\AccountController::period * @dataProvider dateRangeProvider @@ -198,6 +304,17 @@ class AccountControllerTest extends TestCase $response->assertStatus(200); } + /** + * @covers \FireflyIII\Http\Controllers\Chart\AccountController::period + * @expectedExceptionMessage YYYY-MM-DD + */ + public function testPeriodBadDate() + { + $this->be($this->user()); + $response = $this->get(route('chart.account.period', [1, 'bcdefed'])); + $response->assertStatus(500); + } + /** * @covers \FireflyIII\Http\Controllers\Chart\AccountController::report * @covers \FireflyIII\Http\Controllers\Chart\AccountController::accountBalanceChart @@ -221,10 +338,11 @@ class AccountControllerTest extends TestCase */ public function testRevenueAccounts(string $range) { + $account = factory(Account::class)->make(); $generator = $this->mock(GeneratorInterface::class); $accountRepos = $this->mock(AccountRepositoryInterface::class); - $accountRepos->shouldReceive('getAccountsByType')->withArgs([[AccountType::REVENUE]])->andReturn(new Collection); + $accountRepos->shouldReceive('getAccountsByType')->withArgs([[AccountType::REVENUE]])->andReturn(new Collection([$account])); $generator->shouldReceive('singleSet')->andReturn([]); Steam::shouldReceive('balancesById')->twice()->andReturn([]); diff --git a/tests/Feature/Controllers/Chart/BillControllerTest.php b/tests/Feature/Controllers/Chart/BillControllerTest.php index b0251dc790..1938f8cd55 100644 --- a/tests/Feature/Controllers/Chart/BillControllerTest.php +++ b/tests/Feature/Controllers/Chart/BillControllerTest.php @@ -14,6 +14,7 @@ namespace Tests\Feature\Controllers\Chart; use FireflyIII\Generator\Chart\Basic\GeneratorInterface; use FireflyIII\Helpers\Collector\JournalCollectorInterface; +use FireflyIII\Models\Transaction; use FireflyIII\Repositories\Bill\BillRepositoryInterface; use Illuminate\Support\Collection; use Tests\TestCase; @@ -52,12 +53,13 @@ class BillControllerTest extends TestCase */ public function testSingle() { + $transaction = factory(Transaction::class)->make(); $generator = $this->mock(GeneratorInterface::class); $collector = $this->mock(JournalCollectorInterface::class); $collector->shouldReceive('setAllAssetAccounts')->andReturnSelf()->once(); $collector->shouldReceive('setBills')->andReturnSelf()->once(); - $collector->shouldReceive('getJournals')->andReturn(new Collection)->once(); + $collector->shouldReceive('getJournals')->andReturn(new Collection([$transaction]))->once(); $generator->shouldReceive('multiSet')->once()->andReturn([]); diff --git a/tests/Feature/Controllers/Chart/BudgetControllerTest.php b/tests/Feature/Controllers/Chart/BudgetControllerTest.php index 1f70434c54..82b707c59b 100644 --- a/tests/Feature/Controllers/Chart/BudgetControllerTest.php +++ b/tests/Feature/Controllers/Chart/BudgetControllerTest.php @@ -7,7 +7,7 @@ * See the LICENSE file for details. */ -declare(strict_types = 1); +declare(strict_types=1); namespace Tests\Feature\Controllers\Chart; @@ -17,6 +17,7 @@ use FireflyIII\Generator\Chart\Basic\GeneratorInterface; use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Models\Budget; use FireflyIII\Models\BudgetLimit; +use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use Illuminate\Support\Collection; @@ -74,10 +75,25 @@ class BudgetControllerTest extends TestCase $response->assertStatus(200); } + /** + * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::budgetLimit + * @expectedExceptionMessage This budget limit is not part of this budget. + */ + public function testBudgetLimitWrongLimit() + { + $repository = $this->mock(BudgetRepositoryInterface::class); + $generator = $this->mock(GeneratorInterface::class); + + $this->be($this->user()); + $response = $this->get(route('chart.budget.budget-limit', [1, 8])); + $response->assertStatus(500); + } + /** * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::frontpage * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::getExpensesForBudget * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::spentInPeriodWithout + * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::spentInPeriodMulti * @dataProvider dateRangeProvider * * @param string $range @@ -90,16 +106,94 @@ class BudgetControllerTest extends TestCase $budget = factory(Budget::class)->make(); $budgetLimit = factory(BudgetLimit::class)->make(); $budgetLimit->budget_id = $budget->id; + $transaction = factory(Transaction::class)->make(); - $repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget])); + + $repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget]))->once(); $repository->shouldReceive('getBudgetLimits')->once()->andReturn(new Collection([$budgetLimit])); $repository->shouldReceive('spentInPeriod')->andReturn('-100'); - $collector->shouldReceive('setAllAssetAccounts')->andReturnSelf(); - $collector->shouldReceive('setTypes')->withArgs([[TransactionType::WITHDRAWAL]])->andReturnSelf(); - $collector->shouldReceive('setRange')->andReturnSelf(); - $collector->shouldReceive('withoutBudget')->andReturnSelf(); - $collector->shouldReceive('getJournals')->andReturn(new Collection); + $collector->shouldReceive('setAllAssetAccounts')->andReturnSelf()->once(); + $collector->shouldReceive('setTypes')->withArgs([[TransactionType::WITHDRAWAL]])->andReturnSelf()->once(); + $collector->shouldReceive('setRange')->andReturnSelf()->once(); + $collector->shouldReceive('withoutBudget')->andReturnSelf()->once(); + $collector->shouldReceive('getJournals')->andReturn(new Collection([$transaction]))->once(); + + $generator->shouldReceive('multiSet')->once()->andReturn([]); + + $this->be($this->user()); + $this->changeDateRange($this->user(), $range); + $response = $this->get(route('chart.budget.frontpage')); + $response->assertStatus(200); + } + + /** + * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::frontpage + * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::getExpensesForBudget + * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::spentInPeriodWithout + * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::spentInPeriodMulti + * @dataProvider dateRangeProvider + * + * @param string $range + */ + public function testFrontpageMultiLimit(string $range) + { + $repository = $this->mock(BudgetRepositoryInterface::class); + $generator = $this->mock(GeneratorInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $budget = factory(Budget::class)->make(); + $one = factory(BudgetLimit::class)->make(); + $two = factory(BudgetLimit::class)->make(); + $one->budget_id = $budget->id; + $two->budget_id = $budget->id; + $transaction = factory(Transaction::class)->make(); + + + $repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget]))->once(); + $repository->shouldReceive('getBudgetLimits')->once()->andReturn(new Collection([$one, $two])); + $repository->shouldReceive('spentInPeriod')->andReturn('-100'); + + $collector->shouldReceive('setAllAssetAccounts')->andReturnSelf()->once(); + $collector->shouldReceive('setTypes')->withArgs([[TransactionType::WITHDRAWAL]])->andReturnSelf()->once(); + $collector->shouldReceive('setRange')->andReturnSelf()->once(); + $collector->shouldReceive('withoutBudget')->andReturnSelf()->once(); + $collector->shouldReceive('getJournals')->andReturn(new Collection([$transaction]))->once(); + + $generator->shouldReceive('multiSet')->once()->andReturn([]); + + $this->be($this->user()); + $this->changeDateRange($this->user(), $range); + $response = $this->get(route('chart.budget.frontpage')); + $response->assertStatus(200); + } + + /** + * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::frontpage + * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::getExpensesForBudget + * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::spentInPeriodWithout + * @covers \FireflyIII\Http\Controllers\Chart\BudgetController::spentInPeriodMulti + * @dataProvider dateRangeProvider + * + * @param string $range + */ + public function testFrontpageNoLimits(string $range) + { + $repository = $this->mock(BudgetRepositoryInterface::class); + $generator = $this->mock(GeneratorInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $budget = factory(Budget::class)->make(); + $transaction = factory(Transaction::class)->make(); + + + $repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget])); + $repository->shouldReceive('getBudgetLimits')->once()->andReturn(new Collection); + $repository->shouldReceive('spentInPeriod')->andReturn('-100'); + + $collector->shouldReceive('setAllAssetAccounts')->andReturnSelf()->once(); + $collector->shouldReceive('setTypes')->withArgs([[TransactionType::WITHDRAWAL]])->andReturnSelf()->once(); + $collector->shouldReceive('setRange')->andReturnSelf()->once(); + $collector->shouldReceive('withoutBudget')->andReturnSelf()->once(); + $collector->shouldReceive('getJournals')->andReturn(new Collection([$transaction]))->once(); $generator->shouldReceive('multiSet')->once()->andReturn([]); diff --git a/tests/Feature/Controllers/Chart/BudgetReportControllerTest.php b/tests/Feature/Controllers/Chart/BudgetReportControllerTest.php new file mode 100644 index 0000000000..58efc5e3ab --- /dev/null +++ b/tests/Feature/Controllers/Chart/BudgetReportControllerTest.php @@ -0,0 +1,115 @@ +mock(GeneratorInterface::class); + $pieChart = $this->mock(MetaPieChartInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $budgetRepos = $this->mock(BudgetRepositoryInterface::class); + + $pieChart->shouldReceive('setAccounts')->once()->andReturnSelf(); + $pieChart->shouldReceive('setBudgets')->once()->andReturnSelf(); + $pieChart->shouldReceive('setStart')->once()->andReturnSelf(); + $pieChart->shouldReceive('setEnd')->once()->andReturnSelf(); + $pieChart->shouldReceive('setCollectOtherObjects')->once()->andReturnSelf()->withArgs([false]); + $pieChart->shouldReceive('generate')->withArgs(['expense', 'account'])->andReturn([])->once(); + $generator->shouldReceive('pieChart')->andReturn([])->once(); + + $this->be($this->user()); + $response = $this->get(route('chart.budget.account-expense', ['1', '1', '20120101', '20120131', 0])); + $response->assertStatus(200); + } + + /** + * @covers \FireflyIII\Http\Controllers\Chart\BudgetReportController::budgetExpense + */ + public function testBudgetExpense() + { + $generator = $this->mock(GeneratorInterface::class); + $pieChart = $this->mock(MetaPieChartInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $budgetRepos = $this->mock(BudgetRepositoryInterface::class); + + $pieChart->shouldReceive('setAccounts')->once()->andReturnSelf(); + $pieChart->shouldReceive('setBudgets')->once()->andReturnSelf(); + $pieChart->shouldReceive('setStart')->once()->andReturnSelf(); + $pieChart->shouldReceive('setEnd')->once()->andReturnSelf(); + $pieChart->shouldReceive('setCollectOtherObjects')->once()->andReturnSelf()->withArgs([false]); + $pieChart->shouldReceive('generate')->withArgs(['expense', 'budget'])->andReturn([])->once(); + $generator->shouldReceive('pieChart')->andReturn([])->once(); + + $this->be($this->user()); + $response = $this->get(route('chart.budget.budget-expense', ['1', '1', '20120101', '20120131', 0])); + $response->assertStatus(200); + } + + /** + * @covers \FireflyIII\Http\Controllers\Chart\BudgetReportController::mainChart + * @covers \FireflyIII\Http\Controllers\Chart\BudgetReportController::filterBudgetLimits + * @covers \FireflyIII\Http\Controllers\Chart\BudgetReportController::getExpenses + * @covers \FireflyIII\Http\Controllers\Chart\BudgetReportController::groupByBudget + */ + public function testMainChart() + { + $generator = $this->mock(GeneratorInterface::class); + $pieChart = $this->mock(MetaPieChartInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $budgetRepos = $this->mock(BudgetRepositoryInterface::class); + + $one = factory(BudgetLimit::class)->make(); + $one->budget_id = 1; + $two = factory(BudgetLimit::class)->make(); + $two->budget_id = 1; + $two->start_date = new Carbon('2012-01-01'); + $two->end_date = new Carbon('2012-01-31'); + $transaction = factory(Transaction::class)->make(); + $transaction->transaction_amount = '-100'; + + $budgetRepos->shouldReceive('getAllBudgetLimits')->andReturn(new Collection([$one, $two]))->once(); + + + $collector->shouldReceive('setAccounts')->andReturnSelf(); + $collector->shouldReceive('setRange')->andReturnSelf(); + $collector->shouldReceive('setTypes')->withArgs([[TransactionType::WITHDRAWAL, TransactionType::TRANSFER]])->andReturnSelf(); + $collector->shouldReceive('setTypes')->withArgs([[TransactionType::DEPOSIT, TransactionType::TRANSFER]])->andReturnSelf(); + $collector->shouldReceive('disableFilter')->andReturnSelf(); + $collector->shouldReceive('setBudgets')->andReturnSelf(); + $collector->shouldReceive('withOpposingAccount')->andReturnSelf(); + $collector->shouldReceive('getJournals')->andReturn(new Collection([$transaction])); + $generator->shouldReceive('multiSet')->andReturn([])->once(); + + $this->be($this->user()); + $response = $this->get(route('chart.budget.main', ['1', '1', '20120101', '20120131', 0])); + $response->assertStatus(200); + } + +} \ No newline at end of file diff --git a/tests/Feature/Controllers/Chart/CategoryControllerTest.php b/tests/Feature/Controllers/Chart/CategoryControllerTest.php index b2e06f7e5c..d3b6b74da5 100644 --- a/tests/Feature/Controllers/Chart/CategoryControllerTest.php +++ b/tests/Feature/Controllers/Chart/CategoryControllerTest.php @@ -45,7 +45,7 @@ class CategoryControllerTest extends TestCase $repository->shouldReceive('spentInPeriod')->andReturn('0'); $repository->shouldReceive('earnedInPeriod')->andReturn('0'); - $repository->shouldReceive('firstUseDate')->andReturn(new Carbon)->once(); + $repository->shouldReceive('firstUseDate')->andReturn(new Carbon('1900-01-01'))->once(); $accountRepos->shouldReceive('getAccountsByType')->withArgs([[AccountType::DEFAULT, AccountType::ASSET]])->andReturn(new Collection)->once(); $generator->shouldReceive('multiSet')->once()->andReturn([]);