Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update job #95

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added UpdateJobTest.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 43 additions & 4 deletions app/Http/Controllers/Api/V1/JobController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Http\Requests\UpdateJobRequest;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Models\Job;

class JobController extends Controller
Expand All @@ -16,9 +19,9 @@ public function index(Request $request)
try {
$page = $request->input('page', 1);
$size = $request->input('size', 10);

$jobs = Job::paginate($size, ['id', 'title', 'description', 'location', 'salary', 'job_type'], 'page', $page);

return response()->json([
'message' => 'Job listings retrieved successfully.',
'data' => $jobs->items(),
Expand Down Expand Up @@ -58,9 +61,45 @@ public function show(string $id)
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)

public function update(UpdateJobRequest $request, string $id): JsonResponse
{
//
if (empty($id)) {
return response()->json([
'message' => 'Job post id is missing',
], Response::HTTP_METHOD_NOT_ALLOWED);
}

$validated = $request->validated();

$job = Job::find($id);
if (!$job->users->contains(auth()->id())) {
return response()->json([
'message' => 'Invalid job post id',
], Response::HTTP_NOT_FOUND);
}

$updateJob = $job->update($validated);

if ($updateJob) {
$job->users()->attach(auth()->id());

return response()->json([
'message' => 'Job details updated successfully',
'status_code' => Response::HTTP_OK,
'data' =>
[
'title' => $job->title,
'description' => $job->description,
'location' => $job->location,
'salary' => $job->salary,
'job_type' => $job->job_type,
'company_name' => $job->company_name,
'created_at' => $job->created_at->toDateTimeString(),
'updated_at' => $job->updated_at->toDateTimeString(),
],
]);
}
}

/**
Expand Down
47 changes: 47 additions & 0 deletions app/Http/Requests/UpdateJobRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace App\Http\Requests;

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\Response;

class UpdateJobRequest 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 [
'title' => 'required|string|max:255',
'description' => 'required|string',
'location' => 'required|string|max:255',
'salary' => 'required|string|max:255',
'job_type' => 'required|string|max:255',
'company_name' => 'required|string|max:255',
];
}

protected function failedValidation(Validator $validator)
{
$response = [
'status_code' => Response::HTTP_BAD_REQUEST,
'error' => 'Bad request',
'message' => $validator->errors()->all()
];

throw new HttpResponseException(response()->json($response, Response::HTTP_BAD_REQUEST));
}
}
2 changes: 1 addition & 1 deletion app/Models/Job.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ class Job extends Model

public function users()
{
return $this->belongsToMany(User::class, 'job_user')->using(JobUser::class);
return $this->belongsToMany(User::class, 'job_users', 'job_id', 'user_id')->using(JobUser::class);
}
}
6 changes: 4 additions & 2 deletions app/Models/JobUser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Pivot;

class JobUser extends Model

class JobUser extends Pivot
{
use HasFactory, HasUuids;

Expand All @@ -30,4 +31,5 @@ class JobUser extends Model
* @var string
*/
protected $keyType = 'string';

}
2 changes: 1 addition & 1 deletion app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public function organisations(): BelongsToMany

public function jobs(): BelongsToMany
{
return $this->belongsToMany(Job::class, 'job_user')->using(JobUser::class);
return $this->belongsToMany(Job::class, 'job_users', 'user_id', 'job_id')->using(JobUser::class);
}

public function products(): HasMany
Expand Down
6 changes: 4 additions & 2 deletions database/factories/JobFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ class JobFactory extends Factory
*
* @return array<string, mixed>
*/

protected $model = Job::class;

public function definition(): array
{
$user = User::factory()->create();
Expand All @@ -29,8 +31,8 @@ public function definition(): array
'salary' => $this->faker->numberBetween(30000, 150000) . ' per year',
'job_type' => $this->faker->randomElement(['Full-time', 'Part-time', 'Contract']),
'company_name' => $this->faker->company,
'user_id' => User::factory(),
'organisation_id' => User::factory()->create()->organisation_id,
'user_id' => $user->id,
'organisation_id' => $organisation->org_id,
];
}
}
4 changes: 3 additions & 1 deletion database/migrations/2024_07_23_151221_add_to_jobs_table.php
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@


<?php

use Illuminate\Database\Migrations\Migration;
Expand Down Expand Up @@ -26,7 +28,7 @@ public function down(): void
Schema::table('jobs', function (Blueprint $table) {
$table->dropForeign(['user_id']);
$table->dropForeign(['organisation_id']);

$table->dropColumn('salary');
$table->dropColumn('user_id');
$table->dropColumn('organisation_id');
Expand Down
8 changes: 8 additions & 0 deletions database/seeders/DatabaseSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

// use Illuminate\Database\Console\Seeds\WithoutModelEvents;

use App\Models\Job;
use App\Models\Organisation;
use App\Models\Profile;
use App\Models\User;
Expand Down Expand Up @@ -41,8 +42,15 @@ public function run(): void
$organisation2->users()->attach([$user1->id, $user2->id]);
$organisation3->users()->attach($user2->id);

$job1 = Job::factory()->create();
$job2 = Job::factory()->create();
$job1->users()->attach($user1->id);
$job2->users()->attach($user2->id);


$this->call(CategoriesTableSeeder::class);
$this->call([ArticlesTableSeeder::class]);
$this->call(UserJobSeeder::class);

}
}
26 changes: 26 additions & 0 deletions database/seeders/UserJobSeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Database\Seeders;

use App\Models\Job;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class UserJobSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$users = User::factory()->count(10)->create();

foreach ($users as $user) {
$jobs = Job::factory()->count(5)->create();
foreach ($jobs as $job) {
$user->jobs()->attach($job->id);
}
}
}
}
3 changes: 2 additions & 1 deletion routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
Route::middleware('auth:api')->group(function() {
Route::post('/products', [ProductController::class, 'store']);
});

Route::middleware('throttle:10,1')->get('/help-center/topics/search', [ArticleController::class, 'search']);
Route::post('/contact', [ContactController::class, 'sendInquiry']);

Expand All @@ -63,6 +63,7 @@
Route::apiResource('/features', FeatureController::class);
Route::apiResource('/plans', SubscriptionController::class);
Route::post('/organisations', [OrganisationController::class, 'store']);
Route::apiResource('jobs', JobController::class);
});

Route::middleware('auth.jwt')->group(function () {
Expand Down
130 changes: 130 additions & 0 deletions tests/Feature/UpdateJobTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php

namespace Tests\Feature;

use App\Models\Job;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use Tymon\JWTAuth\Facades\JWTAuth;

class UpdateJobTest extends TestCase
{
use RefreshDatabase;

public function test_it_returns_successful_response_with_valid_id()
{
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);

$job = Job::factory()->create();

$user->jobs()->attach($job->id);

$updateJob = [
'title' => 'Music Idustry',
'description' => 'To update music industry',
'location' => 'Las Vegas',
'salary' => '40000',
'job_type' => 'Contract',
'company_name' => 'HNG',
];

$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('patch', "api/v1/jobs/{$job->id}", $updateJob);

$response->assertStatus(200)
->assertJsonStructure([
'message',
'status_code',
'data' => [
'title',
'description',
'location',
'salary',
'job_type',
'company_name',
'created_at',
'updated_at'
],
]);
}


public function test_it_returns_error_response_with_invalid_job_post_id()
{

$user = User::factory()->create();
$token = JWTAuth::fromUser($user);
$job = Job::factory()->create();
$user->jobs()->attach($job->id);

$user2 = User::factory()->create();
JWTAuth::fromUser($user);
$job2 = Job::factory()->create();
$user2->jobs()->attach($job2->id);

$invalidJobId = $job2->id;
$updateJob = [
'title' => 'Music Idustry',
'description' => 'To update music industry',
'location' => 'Las Vegas',
'salary' => '40000',
'job_type' => 'Contract',
'company_name' => 'HNG',
];


$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('patch', "api/v1/jobs/{$invalidJobId}", $updateJob);

$response->assertStatus(404)
->assertJsonStructure([
'message',
]);
}


public function test_it_returns_error_response_with_missing_job_post_id()
{
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);

$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('patch', 'api/v1/jobs/');

$response->assertStatus(405);
}


public function test_it_returns_error_response_with_invalid_request_body()
{
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);


$job = Job::factory()->create();
$invalidJobData = [
'title' => '',
'description' => '',
'location' => '',
'salary' => '',
'job_type' => '',
'company_name' => '',
];

$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('patch', "api/v1/jobs/{$job->id}", $invalidJobData);

$response->assertStatus(400)
->assertJsonStructure([
'status_code',
'message',
'error'
]);
}
}
Loading