Skip to content

Commit adcaa20

Browse files
save progress
1 parent 99f284f commit adcaa20

File tree

10 files changed

+354
-215
lines changed

10 files changed

+354
-215
lines changed

backend/app/Http/Controllers/CountryController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ class CountryController extends Controller
1414
public function all()
1515
{
1616
// calculate the number of users from each country by using the Eloquent ORM
17-
$countries = Country::withCount('users')->get();
17+
$countries = Country::query()
18+
->withCount('users')
19+
->whereHas('users')
20+
->get();
1821
// return the response as a JSON with the HTTP status code 200 and the header Content-Type: application/json
1922
return response()->json($countries, 200);
2023
}

backend/app/Http/Controllers/UserController.php

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ class UserController extends Controller
2626
// GET /users?dateFrom=&dateTo=&country=&page=&perPage= - This endpoint is used to retrieve a list of all users from the database.
2727
// dateFrom: nullable, unix timestamp, if provided, the users should be filtered by the date_of_birth field to only include users that were born after or on the provided date.
2828
// dateTo: nullable, unix timestamp, if provided, the users should be filtered by the date_of_birth field to only include users that were born before or on the provided date.
29-
// Laraver can't validate the dateFrom and dateTo parameters, so we have to do it manually by regexp
3029
public function index(Request $request)
3130
{
3231
// Validate the request
@@ -48,7 +47,6 @@ public function index(Request $request)
4847

4948
// Filter the users based on the provided country and date_of_birth range
5049
$usersQuery = \App\Models\User::query()
51-
// ->with('country')
5250
->dateRange($request->input('dateFrom'), $request->input('dateTo'))
5351
->country($request->input('country'));
5452

@@ -63,7 +61,7 @@ public function index(Request $request)
6361
public function show($id)
6462
{
6563
// Get the user from the database OR fail
66-
return new UserResource(
64+
return UserResource::make(
6765
\App\Models\User::findOrFail($id)
6866
);
6967
}
@@ -79,20 +77,18 @@ public function update(Request $request, $id)
7977
'country_name' => 'required|string',
8078
]);
8179
$user = \App\Models\User::findOrFail($id);
82-
// Get the country from the database
83-
$country = \App\Models\Country::where('name', $request->input('country_name'))->first();
8480
// // Get or create the country
85-
// $country = \App\Models\Country::firstOrCreate([
86-
// 'name' => $request->input('country_name'),
87-
// ]);
81+
$country = \App\Models\Country::firstOrCreate([
82+
'name' => $request->input('country_name'),
83+
]);
8884
// Update the user
8985
$user->first_name = $request->input('first_name');
9086
$user->last_name = $request->input('last_name');
9187
$user->date_of_birth = $request->input('date_of_birth');
9288
$user->country_id = $country->id;
9389
$user->save();
9490

95-
return new UserResource($user);
91+
return UserResource::make($user);
9692
}
9793

9894
// DELETE /users/{id} - This endpoint is used to delete a specific user from the database. The {id} path parameter should be replaced with the id of the user you want to delete.
@@ -129,6 +125,6 @@ public function store(Request $request)
129125
]);
130126
$user->save();
131127

132-
return new UserResource($user);
128+
return UserResource::make($user);
133129
}
134130
}

backend/tests/Unit/AppTest.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
namespace Tests\Unit;
4+
5+
use Carbon\Carbon;
6+
7+
// Here we are testing only the public api of the app, without the access to the database, models, etc.
8+
class AppTest extends \Illuminate\Foundation\Testing\TestCase
9+
{
10+
use \Tests\CreatesApplication;
11+
use \Illuminate\Foundation\Testing\RefreshDatabase;
12+
13+
public function testUpdateCountriesStatsWhenUserUpdate()
14+
{
15+
// Create 2 users with same country by using the POST /api/users requests
16+
$userID = $this->post('/api/users', [
17+
'first_name' => 'John',
18+
'last_name' => 'Doe',
19+
'country_name' => 'USA',
20+
'date_of_birth' => Carbon::now()->subYears(30)->timestamp,
21+
])->json('id');
22+
$this->post('/api/users', [
23+
'first_name' => 'Jane',
24+
'last_name' => 'Doe',
25+
'country_name' => 'USA',
26+
'date_of_birth' => Carbon::now()->subYears(30)->timestamp,
27+
])->json();
28+
29+
// change the country of the first user
30+
$this->patch('/api/users/' . $userID, [
31+
'first_name' => 'John',
32+
'last_name' => 'Doe',
33+
'country_name' => 'Canada',
34+
'date_of_birth' => Carbon::now()->subYears(30)->timestamp,
35+
]);
36+
37+
// check that the country stats are updated
38+
$stats = $this->get('/api/countries');
39+
// should return 2 countries
40+
$stats->assertJsonCount(2);
41+
// should return 1 user for the first country
42+
$stats->assertJsonFragment([
43+
'name' => 'Canada',
44+
'users_count' => 1,
45+
]);
46+
// should return 1 user for the second country
47+
$stats->assertJsonFragment([
48+
'name' => 'USA',
49+
'users_count' => 1,
50+
]);
51+
}
52+
53+
public function testNoCountryWithoutUsers()
54+
{
55+
// Create a user by using the POST /api/users request
56+
$userID = $this->post('/api/users', [
57+
'first_name' => 'John',
58+
'last_name' => 'Doe',
59+
'country_name' => 'USA',
60+
'date_of_birth' => Carbon::now()->subYears(30)->timestamp,
61+
])->json('id');
62+
// Change the country of the user
63+
$this->patch('/api/users/' . $userID, [
64+
'first_name' => 'John',
65+
'last_name' => 'Doe',
66+
'country_name' => 'Canada',
67+
'date_of_birth' => Carbon::now()->subYears(30)->timestamp,
68+
]);
69+
// get the country stats
70+
$stats = $this->get('/api/countries');
71+
// should return only 1 country
72+
$stats->assertJsonCount(1);
73+
$stats->assertJsonFragment([
74+
'name' => 'Canada',
75+
'users_count' => 1,
76+
]);
77+
}
78+
}

backend/tests/Unit/Routes/CountriesTest.php

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@ public function testCountriesRoute()
1212
{
1313
// Create 3 countries
1414
$countries = \App\Models\Country::factory()->count(3)->create();
15-
// Create a users table with 10 users. Each user will be assigned a random country_id
16-
$users = \App\Models\User::factory()->count(10)->create(
15+
// Create a users for each country
16+
foreach ($countries as $country) {
17+
\App\Models\User::factory()->create([
18+
'country_id' => $country->id,
19+
]);
20+
}
21+
// Create another 10 users. Each user will be assigned a random country_id
22+
\App\Models\User::factory()->count(10)->create(
1723
function ($user) use ($countries) {
1824
return [
1925
'country_id' => $countries->random()->id,
@@ -24,11 +30,36 @@ function ($user) use ($countries) {
2430
$response = $this->get('/api/countries');
2531
// Check that the response is contains the correct data for each country
2632
foreach ($countries as $country) {
33+
$usersCount = $country->users()->count();
2734
$response->assertJsonFragment([
2835
'id' => $country->id,
2936
'name' => $country->name,
30-
'users_count' => $users->where('country_id', $country->id)->count(),
37+
'users_count' => $usersCount,
3138
]);
3239
}
3340
}
41+
42+
// should ignore a countries with no users
43+
public function testCountriesRouteIgnoreCountriesWithNoUsers()
44+
{
45+
// Create 3 countries
46+
$countries = \App\Models\Country::factory()->count(3)->create();
47+
// Create only 1 user and assign it to the first country
48+
$users = \App\Models\User::factory()->count(1)->create(
49+
function ($user) use ($countries) {
50+
return [
51+
'country_id' => $countries->first()->id,
52+
];
53+
}
54+
);
55+
56+
// Get the response from the route
57+
$response = $this->get('/api/countries');
58+
// Check that the response is contains only the first country
59+
$response->assertJson([[
60+
'id' => $countries->first()->id,
61+
'name' => $countries->first()->name,
62+
'users_count' => 1,
63+
]]);
64+
}
3465
}

0 commit comments

Comments
 (0)