Skip to content

Commit d1e669e

Browse files
committed
Example test register feature
1 parent 2fd912c commit d1e669e

30 files changed

+1004
-269
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ Homestead.json
99
Homestead.yaml
1010
npm-debug.log
1111
yarn-error.log
12+
phpunit.xml

Diff for: app/Http/Controllers/Web/HomeController.php

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace App\Http\Controllers\Web;
4+
5+
use App\Http\Controllers\Controller;
6+
7+
class HomeController extends Controller
8+
{
9+
public function index()
10+
{
11+
return view('home');
12+
}
13+
}

Diff for: app/Http/Controllers/Web/RegisterController.php

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
namespace App\Http\Controllers\Web;
4+
5+
use App\Http\Controllers\Controller;
6+
use App\Http\Requests\Web\RegisterRequest;
7+
use App\Services\Web\UserService;
8+
use Illuminate\Support\Facades\Mail;
9+
use App\Mail\UserRegistered;
10+
use Illuminate\Http\Request;
11+
12+
class RegisterController extends Controller
13+
{
14+
protected $userService;
15+
16+
public function __construct(UserService $userService)
17+
{
18+
$this->userService = $userService;
19+
}
20+
21+
/**
22+
* Show register form
23+
*
24+
* @return \Illuminate\Contracts\View\View
25+
*/
26+
public function showFormRegister()
27+
{
28+
return view('auth.register');
29+
}
30+
31+
public function showRegisterSuccess()
32+
{
33+
return view('auth.register_success');
34+
}
35+
36+
public function register(RegisterRequest $request)
37+
{
38+
$inputs = $request->all(['name', 'email', 'password']);
39+
40+
$user = $this->userService->create($inputs);
41+
42+
Mail::to($user)->send(new UserRegistered($user->getKey(), $user->name));
43+
44+
return redirect()->action([static::class, 'showRegisterSuccess']);
45+
}
46+
47+
public function verify(Request $request)
48+
{
49+
$user = $this->userService->findById($request->route('id'));
50+
if (!$user) {
51+
abort(404);
52+
}
53+
54+
if (!$user->hasVerifiedEmail()) {
55+
$this->userService->verifyUser($user);
56+
}
57+
58+
return view('auth.verify.message');
59+
}
60+
61+
public function showFormVerification()
62+
{
63+
return view('auth.verify.resend');
64+
}
65+
66+
public function resendVerificationLink(Request $request)
67+
{
68+
$user = $this->userService->findByEmail($request->input('email'));
69+
70+
if ($user && !$user->hasVerifiedEmail()) {
71+
Mail::to($user)->send(new UserRegistered($user->getKey(), $user->name));
72+
}
73+
74+
return redirect()->action([static::class, 'showFormVerification'])->with('resent', true);
75+
}
76+
}

Diff for: app/Http/Requests/Web/RegisterRequest.php

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace App\Http\Requests\Web;
4+
5+
use Illuminate\Foundation\Http\FormRequest;
6+
use Illuminate\Validation\Rules\Unique;
7+
8+
class RegisterRequest extends FormRequest
9+
{
10+
const NAME_MAX_LENGTH = 255;
11+
12+
const EMAIL_MAX_LENGTH = 255;
13+
14+
const PASSWORD_MIN_LENGTH = 8;
15+
16+
/**
17+
* @return array
18+
*/
19+
public function rules()
20+
{
21+
return [
22+
'name' => ['required', 'string', 'max:' . self::NAME_MAX_LENGTH],
23+
'email' => ['required', 'string', 'email', 'max:' . self::EMAIL_MAX_LENGTH, new Unique('users', 'email')],
24+
'password' => ['required', 'string', 'min:' . self::PASSWORD_MIN_LENGTH, 'confirmed'],
25+
];
26+
}
27+
}

Diff for: app/Mail/UserRegistered.php

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace App\Mail;
4+
5+
use Illuminate\Bus\Queueable;
6+
use Illuminate\Mail\Mailable;
7+
use Illuminate\Queue\SerializesModels;
8+
use Illuminate\Contracts\Queue\ShouldQueue;
9+
use Illuminate\Support\Facades\URL;
10+
11+
class UserRegistered extends Mailable implements ShouldQueue
12+
{
13+
use Queueable, SerializesModels;
14+
15+
protected $userId;
16+
17+
protected $userName;
18+
19+
public function __construct($userId, $userName)
20+
{
21+
$this->userId = $userId;
22+
$this->userName = $userName;
23+
}
24+
25+
/**
26+
* Build the message.
27+
*
28+
* @return $this
29+
*/
30+
public function build()
31+
{
32+
return $this->markdown('emails.user.registered')
33+
->subject('Verify your account')
34+
->with([
35+
'url' => $this->verificationUrl(),
36+
'userName' => $this->userName,
37+
]);
38+
}
39+
40+
private function verificationUrl()
41+
{
42+
return URL::temporarySignedRoute(
43+
'web.register.verify',
44+
now()->addMinutes(60),
45+
['id' => $this->userId]
46+
);
47+
}
48+
}

Diff for: app/Models/User.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
namespace App\Models;
44

55
use Illuminate\Notifications\Notifiable;
6-
use Illuminate\Contracts\Auth\MustVerifyEmail;
76
use Illuminate\Foundation\Auth\User as Authenticatable;
7+
use Illuminate\Support\Facades\Hash;
88

99
class User extends Authenticatable
1010
{
@@ -39,4 +39,16 @@ class User extends Authenticatable
3939
protected $casts = [
4040
'email_verified_at' => 'datetime',
4141
];
42+
43+
public function setPasswordAttribute($value)
44+
{
45+
if ($value) {
46+
$this->attributes['password'] = Hash::make($value);
47+
}
48+
}
49+
50+
public function hasVerifiedEmail()
51+
{
52+
return !is_null($this->email_verified_at);
53+
}
4254
}

Diff for: app/Services/Web/UserService.php

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace App\Services\Web;
4+
5+
use App\Models\User;
6+
7+
class UserService
8+
{
9+
public function create($inputs)
10+
{
11+
return User::create([
12+
'name' => $inputs['name'],
13+
'email' => $inputs['email'],
14+
'password' => $inputs['password'],
15+
]);
16+
}
17+
18+
public function findByEmail($email)
19+
{
20+
return User::where('email', '=', $email)->first();
21+
}
22+
23+
public function findById($id)
24+
{
25+
return User::find($id);
26+
}
27+
28+
public function verifyUser($user)
29+
{
30+
$user->email_verified_at = now();
31+
32+
return $user->save();
33+
}
34+
}

Diff for: phpunit.xml renamed to phpunit.dist.xml

+9-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
<directory suffix="Test.php">./tests/Unit</directory>
1414
</testsuite>
1515

16-
<testsuite name="Feature">
17-
<directory suffix="Test.php">./tests/Feature</directory>
16+
<testsuite name="Integration">
17+
<directory suffix="Test.php">./tests/Integration</directory>
1818
</testsuite>
1919
</testsuites>
2020
<filter>
@@ -24,6 +24,13 @@
2424
</filter>
2525
<php>
2626
<server name="APP_ENV" value="testing"/>
27+
<!-- APP_KEY for integration http test -->
28+
<server name="APP_KEY" value="base64:HaoSf5Y02/vR1a1WGy3qfQ/iZhON6PsLkF8QOBr8RyA= " />
29+
<!-- Disable debug to speed up test -->
30+
<server name="APP_DEBUG" value="false" />
31+
<!-- Using SQLite in memory database test -->
32+
<server name="DB_CONNECTION" value="sqlite" />
33+
<server name="DB_DATABASE" value=":memory:" />
2734
<server name="BCRYPT_ROUNDS" value="4"/>
2835
<server name="CACHE_DRIVER" value="array"/>
2936
<server name="MAIL_DRIVER" value="array"/>

Diff for: readme.md

+12-72
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,12 @@
1-
<p align="center"><img src="https://laravel.com/assets/img/components/logo-laravel.svg"></p>
2-
3-
<p align="center">
4-
<a href="https://travis-ci.org/laravel/framework"><img src="https://travis-ci.org/laravel/framework.svg" alt="Build Status"></a>
5-
<a href="https://packagist.org/packages/laravel/framework"><img src="https://poser.pugx.org/laravel/framework/d/total.svg" alt="Total Downloads"></a>
6-
<a href="https://packagist.org/packages/laravel/framework"><img src="https://poser.pugx.org/laravel/framework/v/stable.svg" alt="Latest Stable Version"></a>
7-
<a href="https://packagist.org/packages/laravel/framework"><img src="https://poser.pugx.org/laravel/framework/license.svg" alt="License"></a>
8-
</p>
9-
10-
## About Laravel
11-
12-
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
13-
14-
- [Simple, fast routing engine](https://laravel.com/docs/routing).
15-
- [Powerful dependency injection container](https://laravel.com/docs/container).
16-
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
17-
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
18-
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
19-
- [Robust background job processing](https://laravel.com/docs/queues).
20-
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
21-
22-
Laravel is accessible, powerful, and provides tools required for large, robust applications.
23-
24-
## Learning Laravel
25-
26-
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
27-
28-
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 1400 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
29-
30-
## Laravel Sponsors
31-
32-
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell).
33-
34-
- **[Vehikl](https://vehikl.com/)**
35-
- **[Tighten Co.](https://tighten.co)**
36-
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
37-
- **[64 Robots](https://64robots.com)**
38-
- **[Cubet Techno Labs](https://cubettech.com)**
39-
- **[Cyber-Duck](https://cyber-duck.co.uk)**
40-
- **[British Software Development](https://www.britishsoftware.co)**
41-
- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)**
42-
- **[DevSquad](https://devsquad.com)**
43-
- [UserInsights](https://userinsights.com)
44-
- [Fragrantica](https://www.fragrantica.com)
45-
- [SOFTonSOFA](https://softonsofa.com/)
46-
- [User10](https://user10.com)
47-
- [Soumettre.fr](https://soumettre.fr/)
48-
- [CodeBrisk](https://codebrisk.com)
49-
- [1Forge](https://1forge.com)
50-
- [TECPRESSO](https://tecpresso.co.jp/)
51-
- [Runtime Converter](http://runtimeconverter.com/)
52-
- [WebL'Agence](https://weblagence.com/)
53-
- [Invoice Ninja](https://www.invoiceninja.com)
54-
- [iMi digital](https://www.imi-digital.de/)
55-
- [Earthlink](https://www.earthlink.ro/)
56-
- [Steadfast Collective](https://steadfastcollective.com/)
57-
- [We Are The Robots Inc.](https://watr.mx/)
58-
- [Understand.io](https://www.understand.io/)
59-
- [Abdel Elrafa](https://abdelelrafa.com)
60-
- [Hyper Host](https://hyper.host)
61-
62-
## Contributing
63-
64-
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
65-
66-
## Security Vulnerabilities
67-
68-
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [[email protected]](mailto:[email protected]). All security vulnerabilities will be promptly addressed.
69-
70-
## License
71-
72-
The Laravel framework is open-source software licensed under the [MIT license](https://opensource.org/licenses/MIT).
1+
# PHP (Laravel) Testing Guideline and Example
2+
3+
## Introduction
4+
- Example in folder [tests](./tests)
5+
- Guideline document in folder [docs](./docs)
6+
7+
## Running
8+
```bash
9+
composer install
10+
cp phpunit.dist.xml phpunit.xml
11+
./vendor/bin/phpunit
12+
```

Diff for: resources/views/auth/register.blade.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<div class="card-header">{{ __('Register') }}</div>
99

1010
<div class="card-body">
11-
<form method="POST" action="{{ route('register') }}">
11+
<form method="POST" action="{{ route('web.register') }}">
1212
@csrf
1313

1414
<div class="form-group row">

Diff for: resources/views/auth/register_success.blade.php

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
@extends('layouts.app')
2+
3+
@section('content')
4+
<div class="container">
5+
<div class="row justify-content-center">
6+
<div class="col-md-8">
7+
<div class="card">
8+
<div class="card-header">{{ __('One more step...') }}</div>
9+
10+
<div class="card-body">
11+
Thanks for registering. Please check your email to verify your account.
12+
13+
{{ __('If you did not receive the email') }}, <a href="{{ route('web.register.resend_verify_link') }}">{{ __('click here to request another') }}</a>.
14+
</div>
15+
</div>
16+
</div>
17+
</div>
18+
</div>
19+
@endsection

Diff for: resources/views/auth/verify.blade.php

-24
This file was deleted.

0 commit comments

Comments
 (0)