Skip to content

Commit

Permalink
Merge pull request UnlockedLabs#64 from PThorpe92/corey210
Browse files Browse the repository at this point in the history
feat: add course controller/model/factory Corey UN-210
  • Loading branch information
chrissantillan authored Jan 23, 2024
2 parents 0a79abe + f5f7936 commit bf56b35
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 1 deletion.
76 changes: 76 additions & 0 deletions app/Http/Controllers/v1/CourseController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace App\Http\Controllers\v1;

use App\Http\Controllers\Controller;
use App\Http\Requests\StoreCourseRequest;
use App\Http\Requests\UpdateCourseRequest;
use App\Http\Resources\CourseResource;
use App\Models\Course;
use Illuminate\Http\Response;

class CourseController extends Controller
{
public function index()
{
$perPage = request()->query('per_page', 10);
$sortBy = request()->query('sort', 'provider_course_name');
$sortOrder = request()->query('order', 'asc');

$query = Course::query();
$query->orderBy($sortBy, $sortOrder);
$courses = $query->paginate($perPage);

return CourseResource::collection($courses);
}

/**
* Store a newly created resource in storage.
*/
public function store(StoreCourseRequest $request)
{
$validated = $request->validated();

$course = Course::create($validated->all());

return CourseResource::collection($course);
}

public function show(string $id)
{
$course = Course::find($id);

if (! $course) {
return response()->json(['error' => 'Course not found'], Response::HTTP_NOT_FOUND);
}

return new CourseResource($course);
}

public function update(UpdateCourseRequest $request, string $id)
{
$validated = $request->validated();
$course = Course::find($id);

if (! $course) {
return response()->json(['error' => 'Course not found'], Response::HTTP_NOT_FOUND);
}

$course->update($validated);

return new CourseResource($course);
}

public function destroy(string $id)
{
$course = Course::find($id);

if (! $course) {
return response()->json(['error' => 'Course not found'], Response::HTTP_NOT_FOUND);
}

$course->delete();

return response(null, Response::HTTP_NO_CONTENT);
}
}
30 changes: 30 additions & 0 deletions app/Http/Requests/StoreCourseRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreCourseRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
// Todo add authorization
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'provider_resource_id' => 'required|string|max:255',
'provider_course_name' => 'required|string|max:255',
];
}
}
29 changes: 29 additions & 0 deletions app/Http/Requests/UpdateCourseRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class UpdateCourseRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'provider_resource_id' => 'nullable|string|max:255',
'provider_course_name' => 'nullable|string|max:255',
];
}
}
19 changes: 19 additions & 0 deletions app/Http/Resources/CourseResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class CourseResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return parent::toArray($request);
}
}
2 changes: 1 addition & 1 deletion app/Models/Courses.php → app/Models/Course.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Courses extends Model
class Course extends Model
{
use HasFactory;

Expand Down
27 changes: 27 additions & 0 deletions database/factories/CourseFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Courses>
*/
class CourseFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
//
'provider_resource_id' => $this->faker->unique()->numberBetween(1, 1000000), // Example: Generate a unique ID between 1 and 100,
'provider_course_name' => $this->faker->word,
'provider_start_at' => $this->faker->date,
'provider_end_at' => $this->faker->date,
];
}
}
18 changes: 18 additions & 0 deletions database/seeders/CourseSeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Database\Seeders;

use App\Models\Courses;
use Illuminate\Database\Seeder;

class CoursesSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
Courses::factory(10)->create(); // Create 10 Provider Platforms using the factory
}
}
7 changes: 7 additions & 0 deletions routes/api.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use App\Http\Controllers\v1\CategoryController;
use App\Http\Controllers\v1\CourseController;
use App\Http\Controllers\v1\EnrollmentController;
use App\Http\Controllers\v1\ProviderPlatformController;
use App\Http\Controllers\v1\UserController;
Expand Down Expand Up @@ -34,6 +35,12 @@
Route::patch('/v1/enrollments/{id}', [EnrollmentController::class, 'update']);
Route::delete('/v1/enrollments/{id}', [EnrollmentController::class, 'destroy']);

Route::get('v1/courses', [CourseController::class, 'index']);
Route::get('/v1/courses/{id}', [CourseController::class, 'show']);
Route::post('/v1/courses', [CourseController::class, 'store']);
Route::patch('/v1/courses/{id}', [CourseController::class, 'update']);
Route::delete('/v1/courses/{id}', [CourseController::class, 'destroy']);

Route::get('/v1/users', [UserController::class, 'index']);
Route::get('/v1/users/{id}', [UserController::class, 'show']);
Route::post('/v1/users', [UserController::class, 'store']);
Expand Down
80 changes: 80 additions & 0 deletions tests/Feature/CourseControllerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

namespace Tests\Feature;

use App\Models\Course;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class CourseControllerTest extends TestCase
{
use RefreshDatabase;

public string $uri = '/api/v1/courses';

// this tests the store method in the controller
public function testCoursesAreCreated()
{
// Create 10 categories using the factory
$courses = Course::factory(10)->create();

// Assert that 10 categories were created
$this->assertCount(10, $courses);
}

// tests the index method in the controller
public function testCoursesIndexReturnsJson()
{
// Create 10 courses using the factory
Course::factory(2)->create();

// Make a GET request to the index method
$response = $this->get($this->uri);

// Assert that the response status code is 200 (OK)
$response->assertStatus(200);

// Assert that the response contains the categories
$response->assertJsonStructure(['data', 'meta', 'links']);
}

// this tests the show method in the controller
public function testGetCourses()
{
$course = Course::factory(1)->create();

$response = $this->get($this->uri.'/'.$course[0]->id);

$response->assertStatus(200);

// Decode the JSON response
$jsonResponse = $response->json();

// Assert that the response contains the category
foreach ($jsonResponse as $key => $value) {
// Skip keys 'created_at' and 'updated_at'
if (in_array($key, ['created_at', 'updated_at'])) {
continue;
}

assert($value, $course[0]->$key);
}
}

// this test the update method in the controller
public function testUpdateCourse()
{
$course = Course::factory(1)->create();
$response = $this->patch($this->uri.'/'.$course[0]->id, ['provider_course_name' => 'TestUpdate']);
$response->assertStatus(200);
assert($response['data']['provider_course_name'] == 'TestNameUpdate');
}

// this tests the destroy method in the controller
public function testDeleteCourse()
{
$course = Course::factory(1)->create();
$response = $this->delete($this->uri.'/'.$course[0]->id);
$response->assertStatus(204);
}
}

0 comments on commit bf56b35

Please sign in to comment.