wip
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Api;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\Models\User;
|
||||
use App\Models\Portfolio;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
class PortfoliosTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected User $user;
|
||||
protected Portfolio $portfolio;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// make user
|
||||
$this->user = User::factory()->create();
|
||||
}
|
||||
|
||||
public function test_can_list_own_portfolios_with_pagination()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
|
||||
Portfolio::factory(10)->create();
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->getJson(route('api.portfolio.index', ['page' => 1, 'itemsPerPage' => 5]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'data' => [['id', 'title', 'owner', 'holdings', 'transactions']],
|
||||
'meta' => ['current_page', 'last_page', 'total'],
|
||||
'links' => ['first', 'last', 'prev', 'next']
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_cannot_list_others_portfolios()
|
||||
{
|
||||
// create portfolios with existing user
|
||||
$this->actingAs($this->user);
|
||||
Portfolio::factory(10)->create();
|
||||
|
||||
// Create a new user
|
||||
$this->actingAs($user = User::factory()->create());
|
||||
Portfolio::factory(1)->create();
|
||||
$this->actingAs($user)
|
||||
->getJson(route('api.portfolio.index', ['page' => 1, 'itemsPerPage' => 5]))
|
||||
->assertOk()
|
||||
->assertJsonCount(1, 'data');
|
||||
}
|
||||
|
||||
public function test_cannot_access_portfolios_when_unauthenticated()
|
||||
{
|
||||
$this->getJson(route('api.portfolio.index'))->assertUnauthorized();
|
||||
}
|
||||
|
||||
public function test_can_create_a_portfolio()
|
||||
{
|
||||
$data = Portfolio::factory()->make()->toArray();
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->postJson(route('api.portfolio.store'), $data)
|
||||
->assertCreated()
|
||||
->assertJsonStructure(['id', 'title', 'owner']);
|
||||
|
||||
$this->assertDatabaseHas('portfolios', ['title' => $data['title']]);
|
||||
}
|
||||
|
||||
public function test_cannot_create_portfolio_without_required_fields()
|
||||
{
|
||||
$this->actingAs($this->user)
|
||||
->postJson(route('api.portfolio.store'), [])
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors(['title']);
|
||||
}
|
||||
|
||||
public function test_can_show_a_portfolio()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$portfolio = Portfolio::factory()->create();
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->getJson(route('api.portfolio.show', $portfolio))
|
||||
->assertOk()
|
||||
->assertJsonStructure(['id', 'title', 'owner']);
|
||||
}
|
||||
|
||||
public function test_cannot_show_nonexistent_portfolio()
|
||||
{
|
||||
$this->actingAs($this->user)
|
||||
->getJson(route('api.portfolio.show', ['portfolio' => 999]))
|
||||
->assertNotFound();
|
||||
}
|
||||
|
||||
public function test_can_update_a_portfolio()
|
||||
{
|
||||
$updatedData = ['title' => 'Updated Portfolio Title'];
|
||||
|
||||
$this->actingAs($this->user);
|
||||
$portfolio = Portfolio::factory()->create();
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->putJson(route('api.portfolio.update', $portfolio), $updatedData)
|
||||
->assertOk()
|
||||
->assertJson($updatedData);
|
||||
|
||||
$this->assertDatabaseHas('portfolios', $updatedData);
|
||||
}
|
||||
|
||||
public function test_shared_user_can_update_portfolio()
|
||||
{
|
||||
// create portfolio
|
||||
$this->actingAs($this->user);
|
||||
$portfolio = Portfolio::factory()->create();
|
||||
|
||||
// share it
|
||||
$otherUser = User::factory()->create();
|
||||
$portfolio->share($otherUser->email, true);
|
||||
|
||||
// shared user tries to update it
|
||||
$this->actingAs($otherUser)
|
||||
->putJson(route('api.portfolio.update', $portfolio), ['title' => 'A brand new updated title'])
|
||||
->assertOk()
|
||||
->assertJsonFragment([
|
||||
'title' => 'A brand new updated title'
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_removed_user_cannot_update_portfolio()
|
||||
{
|
||||
// create portfolio
|
||||
$this->actingAs($this->user);
|
||||
$portfolio = Portfolio::factory()->create();
|
||||
|
||||
// share it
|
||||
$otherUser = User::factory()->create();
|
||||
$portfolio->share($otherUser->email, true);
|
||||
|
||||
// unshare it
|
||||
$otherUser = User::factory()->create();
|
||||
$portfolio->unShare($otherUser->id);
|
||||
|
||||
// shared user tries to update it
|
||||
$this->actingAs($otherUser)
|
||||
->putJson(route('api.portfolio.update', $portfolio), ['Title' => 'A brand new updated title'])
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function test_read_only_user_cannot_update_portfolio()
|
||||
{
|
||||
// create portfolio
|
||||
$this->actingAs($this->user);
|
||||
$portfolio = Portfolio::factory()->create();
|
||||
|
||||
// share it
|
||||
$otherUser = User::factory()->create();
|
||||
$portfolio->share($otherUser->email, false);
|
||||
|
||||
// shared user tries to update it
|
||||
$this->actingAs($otherUser)
|
||||
->putJson(route('api.portfolio.update', $portfolio), ['Title' => 'A brand new updated title'])
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function test_cannot_update_portfolio_without_permission()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$portfolio = Portfolio::factory()->create();
|
||||
|
||||
$otherUser = User::factory()->create();
|
||||
$this->actingAs($otherUser)
|
||||
->putJson(route('api.portfolio.update', $portfolio), ['title' => 'New Title'])
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function test_can_delete_a_portfolio()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$portfolio = Portfolio::factory()->create();
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->deleteJson(route('api.portfolio.destroy', $portfolio))
|
||||
->assertNoContent();
|
||||
|
||||
$this->assertDatabaseMissing('portfolios', ['id' => $portfolio->id]);
|
||||
}
|
||||
|
||||
public function test_cannot_delete_portfolio_without_permission()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$portfolio = Portfolio::factory()->create();
|
||||
|
||||
$otherUser = User::factory()->create();
|
||||
$this->actingAs($otherUser)
|
||||
->deleteJson(route('api.portfolio.destroy', $portfolio))
|
||||
->assertForbidden();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Api;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\Models\User;
|
||||
use App\Models\Portfolio;
|
||||
use App\Models\Transaction;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
class TransactionsTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected User $user;
|
||||
protected Portfolio $portfolio;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// make user
|
||||
$this->user = User::factory()->create();
|
||||
|
||||
// make portfolio
|
||||
$this->portfolio = Portfolio::factory()->makeOne();
|
||||
$this->portfolio->setOwnerIdAttribute($this->user->id);
|
||||
$this->portfolio->save();
|
||||
}
|
||||
|
||||
public function test_can_list_transactions()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
|
||||
Transaction::factory(10)->create();
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->getJson(route('api.transaction.index', ['page' => 1, 'itemsPerPage' => 5]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'data' => [['id', 'symbol', 'transaction_type', 'portfolio_id', 'date']],
|
||||
'meta' => ['current_page', 'last_page', 'total'],
|
||||
'links' => ['first', 'last', 'prev', 'next']
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_cannot_list_others_transactions()
|
||||
{
|
||||
// create transactions with existing user
|
||||
$this->actingAs($this->user);
|
||||
Transaction::factory(10)->create();
|
||||
|
||||
// Create a new user
|
||||
$this->actingAs($user = User::factory()->create());
|
||||
Transaction::factory(1)->create();
|
||||
$this->actingAs($user)
|
||||
->getJson(route('api.transaction.index', ['page' => 1, 'itemsPerPage' => 5]))
|
||||
->assertOk()
|
||||
->assertJsonCount(1, 'data');
|
||||
}
|
||||
|
||||
public function test_cannot_access_transactions_when_unauthenticated()
|
||||
{
|
||||
$this->getJson(route('api.transaction.index'))->assertUnauthorized();
|
||||
}
|
||||
|
||||
public function test_can_create_transaction()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
|
||||
$data = [
|
||||
'symbol' => 'AAPL',
|
||||
'portfolio_id' => $this->portfolio->id,
|
||||
'transaction_type' => 'BUY',
|
||||
'quantity' => 10,
|
||||
'date' => now()->toDateString(),
|
||||
'cost_basis' => 150,
|
||||
];
|
||||
|
||||
$this->postJson(route('api.transaction.store'), $data)
|
||||
->assertCreated()
|
||||
->assertJsonStructure([
|
||||
'id',
|
||||
'symbol',
|
||||
'portfolio_id',
|
||||
'transaction_type',
|
||||
'quantity',
|
||||
'date',
|
||||
'cost_basis',
|
||||
'sale_price'
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_cannot_create_transaction_without_required_fields()
|
||||
{
|
||||
$this->actingAs($this->user)
|
||||
->postJson(route('api.transaction.store'), [
|
||||
'portfolio_id' => $this->portfolio->id,
|
||||
'symbol' => null
|
||||
])
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors(['symbol']);
|
||||
}
|
||||
|
||||
public function test_can_show_a_transaction()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
|
||||
$transaction = Transaction::factory()->create();
|
||||
|
||||
$this->getJson(route('api.transaction.show', $transaction))
|
||||
->assertOk()
|
||||
->assertJsonFragment([
|
||||
'id' => $transaction->id,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_cannot_show_nonexistent_transactions()
|
||||
{
|
||||
$this->actingAs($this->user)
|
||||
->getJson(route('api.transaction.show', ['transaction' => 999]))
|
||||
->assertNotFound();
|
||||
}
|
||||
|
||||
public function test_can_update_a_transaction()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
|
||||
$transaction = Transaction::factory()->create();
|
||||
|
||||
$data = [
|
||||
'symbol' => 'ZZZ',
|
||||
'transaction_type' => 'BUY',
|
||||
'cost_basis' => 200.19,
|
||||
'quantity' => 5
|
||||
];
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->putJson(route('api.transaction.update', $transaction), $data)
|
||||
->assertOk()
|
||||
->assertJsonFragment([
|
||||
'symbol' => 'ZZZ',
|
||||
'transaction_type' => 'BUY',
|
||||
'cost_basis' => 200.19,
|
||||
'quantity' => 5,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_shared_user_can_update_transaction()
|
||||
{
|
||||
// create transaction (and portfolio)
|
||||
$this->actingAs($this->user);
|
||||
$transaction = Transaction::factory()->create();
|
||||
|
||||
// share it
|
||||
$otherUser = User::factory()->create();
|
||||
$transaction->portfolio->share($otherUser->email, true);
|
||||
|
||||
// shared user tries to update it
|
||||
$this->actingAs($otherUser)
|
||||
->putJson(route('api.transaction.update', $transaction), ['symbol' => 'ZZZ'])
|
||||
->assertOk()
|
||||
->assertJsonFragment([
|
||||
'symbol' => 'ZZZ'
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_cannot_update_transaction_without_permission()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$transaction = Transaction::factory()->create();
|
||||
|
||||
$otherUser = User::factory()->create();
|
||||
$this->actingAs($otherUser)
|
||||
->putJson(route('api.transaction.update', $transaction), ['symbol' => 'AAPL'])
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function test_can_delete_a_transaction()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$transaction = Transaction::factory()->create();
|
||||
|
||||
$this->deleteJson(route('api.transaction.destroy', $transaction))
|
||||
->assertNoContent();
|
||||
|
||||
$this->assertDatabaseMissing('transactions', ['id' => $transaction->id]);
|
||||
}
|
||||
|
||||
public function test_cannot_delete_transaction_without_permission()
|
||||
{
|
||||
$this->actingAs($this->user);
|
||||
$transaction = Transaction::factory()->create();
|
||||
|
||||
$otherUser = User::factory()->create();
|
||||
$this->actingAs($otherUser)
|
||||
->deleteJson(route('api.transaction.destroy', $transaction))
|
||||
->assertForbidden();
|
||||
}
|
||||
}
|
||||
@@ -14,50 +14,45 @@ class ApiTokenPermissionsTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
// public function test_api_tokens_can_be_deleted(): void
|
||||
// {
|
||||
// if (! Features::hasApiFeatures()) {
|
||||
// $this->markTestSkipped('API support is not enabled.');
|
||||
// }
|
||||
public function test_api_tokens_can_be_deleted(): void
|
||||
{
|
||||
if (! Features::hasApiFeatures()) {
|
||||
$this->markTestSkipped('API support is not enabled.');
|
||||
}
|
||||
|
||||
// $this->actingAs($user = User::factory()->create());
|
||||
$this->actingAs($user = User::factory()->create());
|
||||
|
||||
// $token = $user->tokens()->create([
|
||||
// 'name' => 'Test Token',
|
||||
// 'token' => Str::random(40),
|
||||
// 'abilities' => ['create', 'read'],
|
||||
// ]);
|
||||
$token = $user->tokens()->create([
|
||||
'name' => 'Test Token',
|
||||
'token' => Str::random(40),
|
||||
'abilities' => [],
|
||||
]);
|
||||
|
||||
// Livewire::test(ApiTokenManager::class)
|
||||
// ->set(['apiTokenIdBeingDeleted' => $token->id])
|
||||
// ->call('deleteApiToken');
|
||||
Livewire::test(ApiTokenManager::class)
|
||||
->set(['apiTokenIdBeingDeleted' => $token->id])
|
||||
->call('deleteApiToken');
|
||||
|
||||
// $this->assertCount(0, $user->fresh()->tokens);
|
||||
// }
|
||||
$this->assertCount(0, $user->fresh()->tokens);
|
||||
}
|
||||
|
||||
// public function test_api_tokens_can_be_created(): void
|
||||
// {
|
||||
// if (! Features::hasApiFeatures()) {
|
||||
// $this->markTestSkipped('API support is not enabled.');
|
||||
// }
|
||||
public function test_api_tokens_can_be_created(): void
|
||||
{
|
||||
if (! Features::hasApiFeatures()) {
|
||||
$this->markTestSkipped('API support is not enabled.');
|
||||
}
|
||||
|
||||
// $this->actingAs($user = User::factory()->create());
|
||||
$this->actingAs($user = User::factory()->create());
|
||||
|
||||
// Livewire::test(ApiTokenManager::class)
|
||||
// ->set(['createApiTokenForm' => [
|
||||
// 'name' => 'Test Token',
|
||||
// 'permissions' => [
|
||||
// 'read',
|
||||
// 'update',
|
||||
// ],
|
||||
// ]])
|
||||
// ->call('createApiToken');
|
||||
Livewire::test(ApiTokenManager::class)
|
||||
->set(['createApiTokenForm' => [
|
||||
'name' => 'Test Token',
|
||||
'permissions' => [],
|
||||
]])
|
||||
->call('createApiToken');
|
||||
|
||||
// $this->assertCount(1, $user->fresh()->tokens);
|
||||
// $this->assertEquals('Test Token', $user->fresh()->tokens->first()->name);
|
||||
// $this->assertTrue($user->fresh()->tokens->first()->can('read'));
|
||||
// $this->assertFalse($user->fresh()->tokens->first()->can('delete'));
|
||||
// }
|
||||
$this->assertCount(1, $user->fresh()->tokens);
|
||||
$this->assertEquals('Test Token', $user->fresh()->tokens->first()->name);
|
||||
}
|
||||
|
||||
// public function test_api_token_permissions_can_be_updated(): void
|
||||
// {
|
||||
@@ -76,10 +71,7 @@ class ApiTokenPermissionsTest extends TestCase
|
||||
// Livewire::test(ApiTokenManager::class)
|
||||
// ->set(['managingPermissionsFor' => $token])
|
||||
// ->set(['updateApiTokenForm' => [
|
||||
// 'permissions' => [
|
||||
// 'delete',
|
||||
// 'missing-permission',
|
||||
// ],
|
||||
// 'permissions' => [],
|
||||
// ]])
|
||||
// ->call('updateApiToken');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user