Laravel test breaks on attaching many-to-many relationship - laravel

I have a test which should test the registration of a default User. The test function looks like the following:
public function testCanRegister()
{
$this->json('POST', '/register', [
'name' => 'John Doe',
'email' => 'johndoe#hotmail.com',
'password' => bcrypt('1234')
])
->assertStatus(200)
->assertJsonFragment([
'id' => 3,
'name' => 'John Doe',
'email' => 'johndoe#hotmail.com'
]);
}
It gives me the following error:
Expected status code 200 but received 500. Failed asserting that 200
is identical to 500.
The function it is testing is this:
public function register(RegisterRequest $request)
{
$validatedData = $request->validated();
$user = new User;
$user->name = $validatedData['name'];
$user->email = $validatedData['email'];
$user->password = bcrypt($validatedData['password']);
$user->roles->attach(1); // give User role.
if (!$user->save()) {
return response()->json('Gebruiker kan niet worden geregistreerd', 500);
}
// Create session for the just registered User.
Auth::attempt([
'email' => $user->email,
'password' => $request->json('password')
]);
return response()->json($user, 200);
}
When I comment the line:
$user->roles->attach(1);
the test succeeds. Any ideas on how I can improve my test so it succeeds? The only thing that isn't working is attaching the role.

like in many to many relation doc
$user = App\User::find(1);
$user->roles()->attach($roleId);
so, when you attach, yo attach on relation, not a collection ...
please not that $user->roles is collection of roles, while $user->roles() is a relation ....
just update your statement to:
$user->roles()->attach(1);

Try $user->roles()->attach(1); After saving user first.
like:
$user->save();
$user->roles()->attach(1);

Related

laravel 8 API : how pass username with Auth as user_id value for store post

I'm building an API with Laravel 8.
I have a posts table with these columns:
id
category_id
user_id
title
body
picture
study_time
likes
tags
When a user is logged in as an author or admin, they can add a new post.
and for user_id field, I want to make that field guarded, I want to show username with JWTAuth::user()->username and register it for user_id column .. so no one can enter any value for it
edit :
when i send request it gives me this error : SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert into posts
this is my store method in PostController:
$data = $request->all();
$validator = Validator::make($data, [
'category_id' => 'required',
'title' => 'required|max:100|unique:categories',
'body' => 'required',
'picture' => 'required',
'study_time' => 'required',
'tags' => 'null|string',
]);
if ($validator->fails()) {
return response(['error' => $validator->errors(), 'Validation Error']);
}
$tags = explode(",", $request->tags);
$post = Post::create($data);
$post->tag($tags);
return response()->json([
'username' => JWTAuth::user()->username,
'post' => $post
], 201);
add this after $data=$request->all():
$data['user_id'] = JWTAuth::user()->id;
or you can use this instead (if you define posts in user model):
JWTAuth::user()->posts()->create($data);
You can use $request->user() to get the current user.
$post = Post::create($data);
$post->tag($tags);
$post->username => JWTAuth::user()->username
return response()->json([
'post' => $post
], 201);

Laravel how to test when coming across redirections Expected status code 200 but received 302

I am using Laravel 5.6, I have a simple test which checks a user is able to be registered, as follows;
public function it_registers_successfully()
{
$user = factory(User::class)->create([ 'password' => bcrypt('foobar') ]);
$payload = [ 'name' => $user->name, 'email' => $user->email, 'password' => 'foobar' ];
$response = $this->post('/api/register', $payload);
$response->assertStatus(200);
}
When i run the test i am receiving the following;
Expected status code 200 but received 302.
Failed asserting that false is true.
I am new to testing, but i think the problem is that the register function checks to see if the user should be logged in on a successful register and then does it, hence the redirection.
I know this is defeating the purpose and going backwards to how its meant to be done, but i would like some advice on how to deal with the redirection and see the 200 status.
The function is as follows;
public $loginAfterSignUp = true;
public function register(RegisterAuthRequest $request)
{
// Build new user collection
$user = new User();
$user->name = $request->name;
$user->email = $request->email;
$user->password = bcrypt($request->password);
// Save user
$user->save();
// Check if user should be automatically logged in
if ($this->loginAfterSignUp) {
return $this->login($request);
}
return response()->json([
'success' => true,
'data' => $user
], 200);
}

Laravel sometimes validation rule not working

I'm trying to implement the sometimes validation rule into one of my projects (Laravel 5.6).
I have a profile page that a user can update their name and password, but i want to make it so that if the user doesnt enter a password, it wont update that field, which is what i thought the sometimes rule was.
The complete update method i am using in my controller is below.
If i leave the password field blank, then it returns a string or min error which it shouldn't be doing.
public function update()
{
$user = Auth::user();
$this->validate(request(), [
'name' => 'required',
'password' => 'sometimes|string|min:6'
]);
$user->name = request('name');
$user->password = bcrypt(request('password'));
$user->save();
return back();
}
Any help would be greatly appreciated.
The problem is that if you leave the password field empty, it is still present in the request. But filled with null
Try this instead:
public function update()
{
$user = Auth::user();
$this->validate(request(), [
'name' => 'required',
'password' => 'nullable|string|min:6'
]);
$user->name = request('name');
if(!is_null(request('password'))) {
$user->password = bcrypt(request('password'));
}
$user->save();
return back();
}
Try to add nullable in validation rule
$this->validate(request(), [
'name' => 'required',
'password' => 'sometimes|nullable|string|min:6'
]);
From Laravel docs:
nullable
The field under validation may be null. This is particularly useful
when validating primitive such as strings and integers that can
contain null values.

Laravel Email Confirmation On Registration

I need to send an email after a new user is created.
But I don't know how to return to the home page without getting an error.
This is what I am doing right now.
User::create([
'name' => $data['name'],
'username' => $data['username'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'phone' => bcrypt($data['phone']),
'confirmation_code' => str_random(30),
]);
Email_function();
if (Auth::attempt(['email' => $data['email'], 'password' => bcrypt($data['password']) ])) {
// Authentication passed...
return redirect('/');
}
I keep getting this as my error message.
SErrorException in SessionGuard.php line 439:
Argument 1 passed to Illuminate\Auth\SessionGuard::login() must implement interface Illuminate\Contracts\Auth\Authenticatable, null given, called in /Applications/XAMPP/xamppfiles/htdocs/sniddl/vendor/laravel/framework/src/Illuminate/Foundation/Auth/RegistersUsers.php on line 63 and defined
Edit:
changed the title to reflect the answer.
Here is a modified create function with an added email function for your register controller
Make sure Request is included in the pages top with namespaces being used:
use Illuminate\Http\Request;
Change the create function in your controller:
protected function create(Request $data)
{
$user = new User;
$user->name = $data->input('name');
$user->username = $data->input('username');
$user->email = $data->input('email');
$user->password = bcrypt($data->input('password'));
$user->phone = bcrypt($data->input('phone'));
$user->confirmation_code = str_random(60);
$user->save();
if ($user->save()) {
$this->sendEmail($user);
return redirect('VIEWPATH.VIEWFILE')->with('status', 'Successfully created user.');
} else {
return redirect('VIEWPATH.VIEWFILE')->with('status', 'User not created.');
}
}
Create the sendEmail function in the same controller that will use Laravels built in email. Make sure you create and your HTML email:
public function sendEmail(User $user)
{
$data = array(
'name' => $user->name,
'code' => $user->confirmation_code,
);
\Mail::queue('EMAILVIEWPATH.HTMLEMAILVIEWFILE', $data, function($message) use ($user) {
$message->subject( 'Subject line Here' );
$message->to($user->email);
});
}
NOTE:
Your going to need to update the VIEWPATH.VIEWFILE and EMAILVIEWPATH.HTMLEMAILVIEWFILE at a minimium in the examples above.
Check the repos below for CONTROLLER :
https://github.com/laravel/laravel/blob/master/app/Http/Controllers/Auth/RegisterController.php
https://github.com/jeremykenedy/laravel-auth/blob/master/app/Http/Controllers/Auth/AuthController.php
REGISTER VIEW(blade) EXAMPLE
https://github.com/jeremykenedy/laravel-auth/blob/master/resources/views/auth/register.blade.php
EMAIL VIEW THAT RECEIVES VARIABLES:
https://github.com/jeremykenedy/laravel-auth/blob/master/resources/views/emails/activateAccount.blade.php
Ok so it turns out, by setting User::create as a variable it allows you to login in the user by returning the variable. Like this.
$user = User::create([
'name' => $data['name'],
'username' => $data['username'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'phone' => bcrypt($data['phone']),
'confirmation_code' => str_random(30),
]);
Email_function();
return $user;

laravel 4.2 user roles with auth and Entrust

I look for to make two interface
Administrator (Administrator role)
Subscriber (subscriber role)
I used for now auth and entrust (Github Link) of Laravel 4
A recording User
in my SubscriptionContoller.php I make this :
public function doRegister(){
$password=Input::get('password');
$data = array(
'email' => Input::get('email'),
'password' => Hash::make($password)
);
$rules = array(
'email' => 'required|email',
'password' => 'required'
);
$messages = array(
'required' => 'The :attribute field is required.',
);
$validator = Validator::make($data, $rules, $messages);
if ($validator->fails()) {
Session::flash('message', 'This email is already registered, please choose another one.');
return Redirect::to('subscription/register')
->withErrors($validator);
} else {
$user = new User;
$role = Role::where('name','=','agency')->first();
$user->email = Input::get('email');
$user->password = Hash::make($password);
$user->save();
$user->roles()->attach($role);
Session::flash('message', 'Successfully created account! Please login to submit your ad.');
return Redirect::to('subscription/dashbord');
}
}
How should i write the routes.php and filters.php ??
Just put this line on top of your routes.php
Entrust::routeNeedsRole( 'subscription*', 'agency' );
More Details:
This will only allow users with agency role to be able to access subscription/* urls. If user didn't have that role, then by default an App::abort(403); will be executed, which will look for 403.blade.php in your views/public/ folder.
If you want to do something specific if user didn't match the role, you can pass the third parameter as follow:
Entrust::routeNeedsRole( 'subscription*', 'agency', Redirect::to('/not-authorized'));

Resources