diff --git a/app/Api/V1/Controllers/BudgetLimitController.php b/app/Api/V1/Controllers/BudgetLimitController.php index 891ae9f098..fe07060205 100644 --- a/app/Api/V1/Controllers/BudgetLimitController.php +++ b/app/Api/V1/Controllers/BudgetLimitController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers; use Carbon\Carbon; +use Exception; use FireflyIII\Api\V1\Requests\AvailableBudgetRequest; use FireflyIII\Api\V1\Requests\BudgetLimitRequest; use FireflyIII\Exceptions\FireflyException; @@ -42,6 +43,7 @@ use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; use Log; +use Throwable; /** * Class BudgetLimitController diff --git a/app/Models/BudgetLimit.php b/app/Models/BudgetLimit.php index 12c7b97612..7559c258b2 100644 --- a/app/Models/BudgetLimit.php +++ b/app/Models/BudgetLimit.php @@ -51,8 +51,8 @@ class BudgetLimit extends Model 'updated_at' => 'datetime', 'start_date' => 'date', 'end_date' => 'date', - 'repeats' => 'boolean', ]; + protected $fillable = ['budget_id', 'start_date', 'end_date', 'amount']; /** * @param string $value diff --git a/tests/Api/V1/Controllers/BudgetLimitControllerTest.php b/tests/Api/V1/Controllers/BudgetLimitControllerTest.php new file mode 100644 index 0000000000..1af35c2f91 --- /dev/null +++ b/tests/Api/V1/Controllers/BudgetLimitControllerTest.php @@ -0,0 +1,329 @@ +. + */ + +declare(strict_types=1); + +namespace Tests\Api\V1\Controllers; + + +use FireflyIII\Models\Budget; +use FireflyIII\Models\BudgetLimit; +use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; +use Laravel\Passport\Passport; +use Log; +use Tests\TestCase; + +/** + * + * Class BudgetLimitControllerTest + */ +class BudgetLimitControllerTest extends TestCase +{ + /** + * + */ + public function setUp(): void + { + parent::setUp(); + Passport::actingAs($this->user()); + Log::debug(sprintf('Now in %s.', \get_class($this))); + } + + /** + * @covers \FireflyIII\Api\V1\Controllers\BudgetLimitController + */ + public function testDelete(): void + { + // mock stuff: + $repository = $this->mock(BudgetRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('destroyBudgetLimit')->once()->andReturn(true); + + // Create a budget limit (just in case). + /** @var Budget $budget */ + $budget = $this->user()->budgets()->first(); + $budgetLimit = BudgetLimit::create( + [ + 'budget_id' => $budget->id, + 'start_date' => '2018-01-01', + 'end_date' => '2018-01-31', + 'amount' => 1, + ] + ); + + // call API + $response = $this->delete('/api/v1/budget_limits/' . $budgetLimit->id); + $response->assertStatus(204); + } + + /** + * Show budget limits by budget, include no dates. + * + * @covers \FireflyIII\Api\V1\Controllers\BudgetLimitController + */ + public function testIndex(): void + { + /** @var Budget $budget */ + $budget = $this->user()->budgets()->first(); + // mock stuff: + $repository = $this->mock(BudgetRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('findNull')->andReturn($budget); + $repository->shouldReceive('getBudgetLimits')->once()->andReturn($budget->budgetlimits()->get()); + + // call API + $params = [ + 'budget_id' => $budget->id, + ]; + $response = $this->get('/api/v1/budget_limits?' . http_build_query($params)); + $response->assertStatus(200); + $response->assertHeader('Content-Type', 'application/vnd.api+json'); + } + + /** + * Show budget limits by budget, include dates. + * + * @covers \FireflyIII\Api\V1\Controllers\BudgetLimitController + */ + public function testIndexNoBudget(): void + { + /** @var Budget $budget */ + $budget = $this->user()->budgets()->first(); + // mock stuff: + $repository = $this->mock(BudgetRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('findNull')->andReturn($budget); + $repository->shouldReceive('getAllBudgetLimits')->once()->andReturn($budget->budgetlimits()->get()); + + // call API + $params = [ + 'start_date' => '2018-01-01', + 'end_date' => '2018-01-31', + ]; + $response = $this->get('/api/v1/budget_limits?' . http_build_query($params)); + $response->assertStatus(200); + $response->assertHeader('Content-Type', 'application/vnd.api+json'); + } + + /** + * Show budget limits by budget, include dates. + * + * @covers \FireflyIII\Api\V1\Controllers\BudgetLimitController + */ + public function testIndexWithDates(): void + { + /** @var Budget $budget */ + $budget = $this->user()->budgets()->first(); + // mock stuff: + $repository = $this->mock(BudgetRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('findNull')->andReturn($budget); + $repository->shouldReceive('getBudgetLimits')->once()->andReturn($budget->budgetlimits()->get()); + + // call API + $params = [ + 'budget_id' => $budget->id, + 'start_date' => '2018-01-01', + 'end_date' => '2018-01-31', + ]; + $response = $this->get('/api/v1/budget_limits?' . http_build_query($params)); + $response->assertStatus(200); + $response->assertHeader('Content-Type', 'application/vnd.api+json'); + } + + /** + * @covers \FireflyIII\Api\V1\Controllers\BudgetLimitController + */ + public function testShow(): void + { + // mock stuff: + $repository = $this->mock(BudgetRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + + // Create a budget limit (just in case). + /** @var Budget $budget */ + $budget = $this->user()->budgets()->first(); + $budgetLimit = BudgetLimit::create( + [ + 'budget_id' => $budget->id, + 'start_date' => '2018-01-01', + 'end_date' => '2018-01-31', + 'amount' => 1, + ] + ); + + + $response = $this->get('/api/v1/budget_limits/' . $budgetLimit->id); + $response->assertStatus(200); + $response->assertHeader('Content-Type', 'application/vnd.api+json'); + } + + /** + * Store new budget limit. + * + * @covers \FireflyIII\Api\V1\Controllers\BudgetLimitController + */ + public function testStore(): void + { + $budget = $this->user()->budgets()->first(); + $budgetLimit = BudgetLimit::create( + [ + 'budget_id' => $budget->id, + 'start_date' => '2018-01-01', + 'end_date' => '2018-01-31', + 'amount' => 1, + ] + ); + $data + = [ + 'budget_id' => $budget->id, + 'start_date' => '2018-01-01', + 'end_date' => '2018-01-31', + 'amount' => 1, + ]; + // mock stuff: + $repository = $this->mock(BudgetRepositoryInterface::class); + $repository->shouldReceive('findNull')->andReturn($budget)->once(); + $repository->shouldReceive('storeBudgetLimit')->andReturn($budgetLimit)->once(); + + + // mock calls: + $repository->shouldReceive('setUser')->once(); + + // call API + $response = $this->post('/api/v1/budget_limits', $data); + $response->assertStatus(200); + $response->assertHeader('Content-Type', 'application/vnd.api+json'); + } + + /** + * Store new budget limit, but give error + * + * @covers \FireflyIII\Api\V1\Controllers\BudgetLimitController + */ + public function testStoreBadBudget(): void + { + $data + = [ + 'budget_id' => '1', + 'start_date' => '2018-01-01', + 'end_date' => '2018-01-31', + 'amount' => 1, + ]; + // mock stuff: + $repository = $this->mock(BudgetRepositoryInterface::class); + $repository->shouldReceive('findNull')->andReturn(null)->once(); + + + // mock calls: + $repository->shouldReceive('setUser')->once(); + + // call API + $response = $this->post('/api/v1/budget_limits', $data); + $response->assertStatus(500); + } + + /** + * Test update of budget limit. + * + * @covers \FireflyIII\Api\V1\Controllers\BudgetLimitController + */ + public function testUpdate(): void + { + $budget = $this->user()->budgets()->first(); + $budgetLimit = BudgetLimit::create( + [ + 'budget_id' => $budget->id, + 'start_date' => '2018-01-01', + 'end_date' => '2018-01-31', + 'amount' => 1, + ] + ); + $data + = [ + 'budget_id' => $budget->id, + 'start_date' => '2018-01-01', + 'end_date' => '2018-01-31', + 'amount' => 2, + ]; + // mock stuff: + $repository = $this->mock(BudgetRepositoryInterface::class); + $repository->shouldReceive('findNull')->andReturn($budget)->once(); + $repository->shouldReceive('updateBudgetLimit')->andReturn($budgetLimit)->once(); + + + // mock calls: + $repository->shouldReceive('setUser')->once(); + + // call API + $response = $this->put('/api/v1/budget_limits/' . $budgetLimit->id, $data); + $response->assertStatus(200); + $response->assertHeader('Content-Type', 'application/vnd.api+json'); + + } + + /** + * Test update of budget limit but submit bad budget. + * + * @covers \FireflyIII\Api\V1\Controllers\BudgetLimitController + */ + public function testUpdateBadBudget(): void + { + $budget = $this->user()->budgets()->first(); + $budgetLimit = BudgetLimit::create( + [ + 'budget_id' => $budget->id, + 'start_date' => '2018-01-01', + 'end_date' => '2018-01-31', + 'amount' => 1, + ] + ); + $data + = [ + 'budget_id' => $budget->id, + 'start_date' => '2018-01-01', + 'end_date' => '2018-01-31', + 'amount' => 2, + ]; + // mock stuff: + $repository = $this->mock(BudgetRepositoryInterface::class); + $repository->shouldReceive('findNull')->andReturn(null)->once(); + + + // mock calls: + $repository->shouldReceive('setUser')->once(); + + // call API + $response = $this->put('/api/v1/budget_limits/' . $budgetLimit->id, $data); + $response->assertStatus(500); + } + +} \ No newline at end of file diff --git a/tests/Unit/TransactionRules/Triggers/HasAnyBudgetTest.php b/tests/Unit/TransactionRules/Triggers/HasAnyBudgetTest.php index a2c7664c40..989660cfba 100644 --- a/tests/Unit/TransactionRules/Triggers/HasAnyBudgetTest.php +++ b/tests/Unit/TransactionRules/Triggers/HasAnyBudgetTest.php @@ -22,6 +22,7 @@ declare(strict_types=1); namespace Tests\Unit\TransactionRules\Triggers; +use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use FireflyIII\TransactionRules\Triggers\HasAnyBudget; use Tests\TestCase; @@ -52,9 +53,21 @@ class HasAnyBudgetTest extends TestCase */ public function testTriggeredNot(): void { - $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); + do { + /** @var TransactionJournal $journal */ + $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); + $count = $journal->transactions()->count(); + } while ($count !== 0); + $journal->budgets()->detach(); $this->assertEquals(0, $journal->budgets()->count()); + + // also detach all transactions: + /** @var Transaction $transaction */ + foreach ($journal->transactions()->get() as $transaction) { + $transaction->budgets()->detach(); + } + $trigger = HasAnyBudget::makeFromStrings('', false); $result = $trigger->triggered($journal); $this->assertFalse($result);