Skip to content

Commit

Permalink
feat: Working concept testing
Browse files Browse the repository at this point in the history
  • Loading branch information
nevinsm committed Oct 21, 2024
1 parent ae2c437 commit 280fe23
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 61 deletions.
54 changes: 45 additions & 9 deletions app/Http/Controllers/API/ConceptController.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public function store(ConceptStoreRequest $request)
DB::commit();
return response()->json([
"id" => $concept->id,
]);
], 201);
} catch (\Throwable $th) {
DB::rollback();

Expand All @@ -139,12 +139,11 @@ public function show(Concept $concept)
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @param \App\Concept $concept
* @return \Illuminate\Http\Response
*/
public function update(Request $request, int $id)
public function update(Request $request, Concept $concept)
{
$concept = Concept::findOrFail($id);
$attributes = $request->all();

// Sync concept categories
Expand All @@ -163,15 +162,49 @@ public function update(Request $request, int $id)
return new Response($concept);
}

/**
* Relate Concepts
*
* @param \Illuminate\Http\Request $request
* @param \App\Concept $concept
* @return \Illuminate\Http\Response
*/
public function relateConcepts(Request $request, Concept $concept)
{
if ($request->user()->cannot('update', $concept)) {
abort(403);
}

$relation_type = $request->input('relation_type');
$related_id = $request->input('related_id');

switch ($relation_type) {
case "broader":
$concept->addBroader($related_id);
break;
case "narrower":
$concept->addNarrower($related_id);
break;
case "related":
$concept->addRelated($related_id);
break;
}

return $concept;
}

/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function deprecate(Request $request, $id)
public function deprecate(Request $request, Concept $concept)
{
$concept = Concept::findOrFail($id);
if ($request->user()->cannot('update', $concept)) {
abort(403);
}

$to = $request->input('to');
if ($to) {
$replaceConcept = Concept::findOrFail($to);
Expand All @@ -180,7 +213,8 @@ public function deprecate(Request $request, $id)
$concept->deprecated = !$concept->deprecated;
$concept->save();
}
return $concept->deprecated ? 'true' : 'false';

return response()->json($concept, 200);
}

/**
Expand All @@ -189,9 +223,11 @@ public function deprecate(Request $request, $id)
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy(Concept $concept)
{
//
$concept->conceptCategories()->detach();
$concept->terms()->delete();
$concept->delete();
}

/**
Expand Down
29 changes: 0 additions & 29 deletions app/Http/Controllers/ConceptController.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,33 +223,4 @@ public function search(Concept $concept)

return $terms->get();
}

/**
* Relate Concepts
*
* @param \App\Concept $concept
* @return \Illuminate\Http\Response
*/
public function relateConcepts($concept_id)
{
$relation_type = $_GET["relation_type"];
$related_id = $_GET["related_id"];

$concept = Concept::findOrFail($concept_id);

switch ($relation_type) {
case "broader":
$concept->addBroader($related_id);
break;
case "narrower":
$concept->addNarrower($related_id);
break;
case "related":
$concept->addRelated($related_id);
break;
}

return $concept;
}

}
4 changes: 2 additions & 2 deletions app/Policies/ConceptPolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ class ConceptPolicy
/**
* Determine whether the user can view any models.
*/
public function viewAny(User $user): bool
public function viewAny(?User $user): bool
{
return true;
}

/**
* Determine whether the user can view the model.
*/
public function view(User $user, Concept $concept): bool
public function view(?User $user, Concept $concept): bool
{
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
Route::get('concepts/reconcile/{id}', 'API\ConceptController@reconcile');
Route::get('concepts/reconcile', 'API\ConceptController@reconcile');

Route::put('concepts/{id}/relate_concept', 'ConceptController@relateConcepts');
Route::put('concepts/{id}/relate_concept', 'API\ConceptController@relateConcepts');
Route::put('concepts/{id}/deprecate', 'API\ConceptController@deprecate');
Route::apiResource('concepts', 'API\ConceptController');

Expand Down
91 changes: 71 additions & 20 deletions tests/Feature/API/ConceptsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@
use App\Models\Concept;
use App\Models\Role;
use App\Models\User;
use App\Models\Vocabulary;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Arr;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;

class ConceptsTest extends TestCase
{
use DatabaseTransactions;

public function test_any_can_list_concepts(): void
{
$response = $this->getJson('/api/concepts');
Expand Down Expand Up @@ -37,12 +42,22 @@ public function test_any_can_reconcile_concept(): void

public function test_authorized_user_can_create_concept(): void
{
$user = User::factory()->create(['role' => 'editor']);
$reviewerRole = Role::whereHas('permissions', function ($query) {
$query->where('label', 'Edit Vocabulary');
})->first();
$user = User::factory()->hasAttached($reviewerRole)->create();
Sanctum::actingAs($user);

$categoryIds = Vocabulary::where('type', 'concept_category')->pluck('id')->toArray();

$response = $this->postJson('/api/concepts', [
'category_id' => 1,
'terms' => [['text' => 'New Term']],
'preferred_term' => 'preferred',
'category_id' => Arr::random($categoryIds),
'alternate_terms' => [
'term1',
'term2',
'term3'
],
]);

$response->assertStatus(201);
Expand All @@ -51,46 +66,65 @@ public function test_authorized_user_can_create_concept(): void
public function test_authorized_user_can_update_concept(): void
{
$reviewerRole = Role::whereHas('permissions', function ($query) {
$query->where('name', 'Edit Vocabulary');
$query->where('label', 'Edit Vocabulary');
})->first();
$user = User::factory()->hasAttached($reviewerRole)->create();
Sanctum::actingAs($user);

$concept = Concept::factory()->create();
$response = $this->putJson("/api/concepts/{$concept->id}", [
'terms' => [['text' => 'Updated Term']],
$conceptCategories = Vocabulary::where('type', 'concept_category')->get()->random(2)->toArray();
$response = $this->patchJson("/api/concepts/{$concept->id}", [
'conceptCategories' => $conceptCategories
]);

$updatedCategories = Concept::find($concept->id)->conceptCategories->toArray();
$keysToRemove = ["pivot"];
$cleanedCategories = array_map(function($item) use ($keysToRemove) {
return array_diff_key($item, array_flip($keysToRemove));
}, $updatedCategories);
$this->assertEqualsCanonicalizing($conceptCategories, $cleanedCategories);

$response->assertStatus(200);
}

public function test_authorized_user_can_update_concept_relationships(): void
{
$user = User::factory()->create(['role' => 'editor']);
$reviewerRole = Role::whereHas('permissions', function ($query) {
$query->where('label', 'Edit Vocabulary');
})->first();
$user = User::factory()->hasAttached($reviewerRole)->create();
Sanctum::actingAs($user);

$concept = Concept::factory()->create();
$response = $this->putJson("/api/concepts/{$concept->id}/relationships", [
'related' => [2, 3],
$relatedConcept = Concept::factory()->create();
$response = $this->putJson("/api/concepts/{$concept->id}/relate_concept", [
'relation_type' => 'broader',
'related_id' => $relatedConcept,
]);

$response->assertStatus(200);
}

public function test_authorized_user_can_deprecate_concept(): void
{
$user = User::factory()->create(['role' => 'editor']);
$reviewerRole = Role::whereHas('permissions', function ($query) {
$query->where('label', 'Edit Vocabulary');
})->first();
$user = User::factory()->hasAttached($reviewerRole)->create();
Sanctum::actingAs($user);

$concept = Concept::factory()->create();
$response = $this->patchJson("/api/concepts/{$concept->id}/deprecate");
$response = $this->putJson("/api/concepts/{$concept->id}/deprecate");

$response->assertStatus(200);
}

public function test_authorized_user_can_delete_concept(): void
{
$user = User::factory()->create(['role' => 'editor']);
$reviewerRole = Role::whereHas('permissions', function ($query) {
$query->where('label', 'Edit Vocabulary');
})->first();
$user = User::factory()->hasAttached($reviewerRole)->create();
Sanctum::actingAs($user);

$concept = Concept::factory()->create();
Expand All @@ -101,7 +135,10 @@ public function test_authorized_user_can_delete_concept(): void

public function test_unauthorized_user_cannot_create_concept(): void
{
$user = User::factory()->create(['role' => 'viewer']);
$nonReviewerRole = Role::whereDoesntHave('permissions', function ($query) {
$query->where('label', 'Edit Vocabulary');
})->first();
$user = User::factory()->hasAttached($nonReviewerRole)->create();
Sanctum::actingAs($user);

$response = $this->postJson('/api/concepts', [
Expand All @@ -114,7 +151,10 @@ public function test_unauthorized_user_cannot_create_concept(): void

public function test_unauthorized_user_cannot_update_concept(): void
{
$user = User::factory()->create(['role' => 'viewer']);
$nonReviewerRole = Role::whereDoesntHave('permissions', function ($query) {
$query->where('label', 'Edit Vocabulary');
})->first();
$user = User::factory()->hasAttached($nonReviewerRole)->create();
Sanctum::actingAs($user);

$concept = Concept::factory()->create();
Expand All @@ -127,31 +167,42 @@ public function test_unauthorized_user_cannot_update_concept(): void

public function test_unauthorized_user_cannot_update_concept_relationships(): void
{
$user = User::factory()->create(['role' => 'viewer']);
$nonReviewerRole = Role::whereDoesntHave('permissions', function ($query) {
$query->where('label', 'Edit Vocabulary');
})->first();
$user = User::factory()->hasAttached($nonReviewerRole)->create();
Sanctum::actingAs($user);

$concept = Concept::factory()->create();
$response = $this->putJson("/api/concepts/{$concept->id}/relationships", [
'related' => [2, 3],
$relatedConcept = Concept::factory()->create();
$response = $this->putJson("/api/concepts/{$concept->id}/relate_concept", [
'relation_type' => 'broader',
'related_id' => $relatedConcept,
]);

$response->assertStatus(403);
}

public function test_unauthorized_user_cannot_deprecate_concept(): void
{
$user = User::factory()->create(['role' => 'viewer']);
$nonReviewerRole = Role::whereDoesntHave('permissions', function ($query) {
$query->where('label', 'Edit Vocabulary');
})->first();
$user = User::factory()->hasAttached($nonReviewerRole)->create();
Sanctum::actingAs($user);

$concept = Concept::factory()->create();
$response = $this->patchJson("/api/concepts/{$concept->id}/deprecate");
$response = $this->putJson("/api/concepts/{$concept->id}/deprecate");

$response->assertStatus(403);
}

public function test_unauthorized_user_cannot_delete_concept(): void
{
$user = User::factory()->create(['role' => 'viewer']);
$nonReviewerRole = Role::whereDoesntHave('permissions', function ($query) {
$query->where('label', 'Edit Vocabulary');
})->first();
$user = User::factory()->hasAttached($nonReviewerRole)->create();
Sanctum::actingAs($user);

$concept = Concept::factory()->create();
Expand Down
Empty file added tests/Unit/.gitkeep
Empty file.

0 comments on commit 280fe23

Please sign in to comment.