I have created a small Laravel project and I am applying unit testing on my project. When I fill wrong credentials in function, it doesn't redirect to the login page and shows error on terminal saying Failed asserting that two strings are equal. Here is my code...
$credentials = [
'email' => 'test#gmail.com',
'password' => 'wrongcode'
];
$this->post('/login', $credentials)->assertRedirect('/login');
But when i change assertRedirect('/login') to assertRedirect('/') , it works fine
$credentials = [
'email' => 'test1234#gmail.com',
'password' => '98756412'
];
$this->post('/login', $credentials)->assertRedirect('/');
assertRedirect checks two string, one of them is an argument of method, 2nd is redirect path. Looks like everything works fine. You write a test, test failed, you have feedback to improve application. In that case, the redirect path is different than expected by you.
There should be 2 different methods for an individual scenario like below.
public function testCorrectCredential() {
$credentials = [
'email' => 'test1234#gmail.com',
'password' => '98756412'
];
$this->post('/login', $credentials)->assertRedirect('/');
}
public function testInCorrectCredential() {
$credentials = [
'email' => 'incorrect#gmail.com',
'password' => '98756412'
];
$this->post('/login', $credentials)->assertRedirect('/incorrect-url');
}
Related
I wrote test:
public function test_hello_world(){
$test = User::create(['name' => 'Test',
'email' => 'test#test.com',
'password' => 'password',
]);
Profile::create([
'user_id' => $test->id,
'name' => 'Test',
'slug' => 'test'
]);
$this->get('/profile/test')
->assertStatus(200);
}
What this code should testing? After get to this url it should display details about profile. If profile with this slug doesn't exist, we have error 404. In this test I create user and profile table (this 2 tables is connection) but after run test I have the error:
Expected response status code [200] but received 404. Failed
asserting that 200 is identical to 404.
Why I have this error since I created profile with this slug? For me the best option will be create testing database with a lot of records and conduct all test on it. Is it possible? How do that?
#Edit
I have a route and controller's method which display user's profile. If I go (in web browser) to localhost/profile/slug, it works, if this profile exist. My controller's method look like this:
public function show($slug) {
$profile = Profile::where('slug', $slug)
->firstOrFail();
return Inertia::render('Profile/Single', [
'profile' => $profile,
]);
}
And route:
Route::get('/profile/{slug}',
[ProfileController::class, 'show'])
->name('profile.show');
According to your requirement you have to create route for getting profile from slug name. You did wrong in single function. Without creating route it will not worked.
So below example may work for you.
For example:-
For creating data
public function createData(){
$user = User::create(['name' => 'Test',
'email' => 'test#test.com',
'password' => 'password',
]);
Profile::create([
'user_id' => $user->id,
'name' => 'Test',
'slug' => 'test'
]);
return redirect()->back()->with('success', 'Data created');
}
For Getting Data
public function getDataBySlug($slug){
$profile = Profile::where('slug',$slug)->firstOrFail();
return redirect('/dashboard')->with('slug', $slug);
}
In route file
you have to mention table name and column name {profile:slug} instead of id
Route::get('/profile/create', 'Controller#createData');
Route::get('/profile/{profile:slug}', 'Controller#getDataBySlug');
Your route definition is wrong please do as above
I have this nested relation im abit unsure how i assertJson the response within the phpunit test.
FilmController
public function show(string $id)
{
$film = Film::with([
'account.user:id,account_id,location_id,name',
'account.user.location:id,city'
])->findOrFail($id);
}
FilmControllerTest
public function getFilmTest()
{
$film = factory(Film::class)->create();
$response = $this->json('GET', '/film/' . $film->id)
->assertStatus(200);
$response
->assertExactJson([
'id' => $film->id,
'description' => $film->description,
'account' => $film->account->toArray(),
'account.user' => $film->account->user->toArray(),
'account.user.location' => $film->account->user->location->toArray()
]);
}
Obviously this isnt working because its returning every column for the user im a little unfamiliar with how you test nested relations with the code you need so im unsure with a toArray can anyone help out?
Testing is a place where you throw DRY (don't repeat yourself) out and replace it with hard coded solutions. Why? simply, you want the test to always produce the same results and not be bound up on model logic, clever methods or similar. Read this amazing article.
Simply hard code the structure you expect to see. If you changed anything in your model to array approach, the test would still pass even thou your name was not in the response. Because you use the same approach for transformation as testing. I have tested a lot of Laravel apps by now and this is the approach i prefers.
$account = $film->account;
$user = $account->user;
$location = $user->location;
$response->assertExactJson([
'description' => $film->description,
'account' => [
'name' => $account->name,
'user' => [
'name' => $user->name,
'location' => [
'city' => $location->city,
],
],
],
]);
Don't test id's the database will handle those and is kinda redundant to test. If you want to check these things i would rather go with assertJsonStructure(), which does not assert the data but checks the JSON keys are properly set. I think it is fair to include both, just always check the JSON structure first as it would likely be the easiest to pass.
$response->assertJsonStructure([
'id',
'description',
'account' => [
'id',
'name',
'user' => [
'id',
'name',
'location' => [
'id',
'city',
],
],
],
]);
I'm developing an API for an application that I'm creating. This application will get all the information from this API (first will auth the user, then get information)
Right now, I'm trying to make the user send a username and password to the API, it validates the information and returns if it's "ok" or "not", very simple to start only. I know all the security involved in this, just need to get this working.
Already managed to send the username and passsword on the API Side (and i'm 100% sure that the data is correctly saved). Though, when I call
$this->Auth->identify($this->request->data);
It always returns false to me (already tried with parameters and without, result is the same).
I'm using the HttpRequester, firefox plugin, to send information.
I've did a debug of $this->request->data to see if the information is correct, and it is. Can't do a find on database since the password is being hashed.
The database password field is a varchar with 300 length (already tried with 255, also no work)
Thanks for the help
EDIT:
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
]
],
]
]);
if($this->request->is('POST')){
//debug($this->request->data);
$user = $this->Auth->identify($this->request->data);
}
Users Table:
protected $_accessible = [
'*' => true,
];
/**
* Hash password
*
*/
protected function _setPassword($password)
{
return (new DefaultPasswordHasher)->hash($password);
}
protected function _getFullName()
{
if(isset($this->_properties['full_name'])){
return ucwords(mb_strtolower($this->_properties['full_name']));
}
}
ps: Also tried doing the following (replacing the variables form post, but also no luck)
$this->request->data['username'] = "xxxx";
$this->request->data['password'] = "zzzz";
Problem is here
'Form' => [
'fields' => [
'username' => 'email', //email is your database field
'password' => 'password' // password is your database field name
]
],
Your code should be
'Form' => [
'fields' => [
'username' => 'username',
'password' => 'password'
]
],
Details check Configuring Authentication Handlers
For a school project I am trying to remove Eloquent from the core of my project (have to work directly with DB, cannot use ORM).
I am now trying to modify the create function of the AuthController, but it does not seem to be updating. (Using XAMPP with PHP7.)
As you can see I tried to replace the User::create default with the DB::insert statement inside of AuthController's create function.
protected function create(array $data)
{
return DB::insert('INSERT INTO users (firstname,lastname,birthday,gender,email,password) values(?,?,?,?,?,?)',
array(
$data['firstname'],
$data['lastname'],
$data['birthday'],
$data['gender'],
$data['email'],
bcrypt($data['password'])
)
);
// OLD FUNCTION BODY:
/*return User::create([
'firstname' => $data['firstname'],
'lastname' => $data['lastname'],
'birthday' => $data['birthday'],
'gender' => $data['gender'],
'email' => $data['email'],
'password' => bcrypt($data['password'])
]);*/
}
But now I keep getting:
FatalThrowableError in AuthController.php line 71: Fatal error: Call to undefined method App\User::create()
I believe that the function needs more than DB::insert, as it says, that it should return a new instance of the User object, but at the moment I cannot even test what this would do as it is still trying to call the old function body. I have even deleted the User::create section alltogether.
Is this a XAMP thing? I had no problem updating and saving other files of this project, but this controller does not make it through it seems like.
Try to clean Laravel cache. Then use this:
return DB::insert(array(
'firstname' => $data['firstname'],
'lastname' => $data['lastname'],
'birthday' => $data['birthday'],
'gender' => $data['gender'],
'email' => $data['email'],
'password' => bcrypt($data['password'])
)
);
If you will still get the error, please post contents of 71th line of AuthController.php
You are returning two entirely different thing.
return DB::insert
vs
return User::create
See what User::create returns and go from there.
So I'm learning Laravel, and I'm trying to create a new user in the database using data entered into a form. In my controller, I'm getting the form data fine, passing it to a validator with some rules which pass fine, but then when I try to create the User, nothing gets added to the database and it redirects to the basic "Whoops, looks like something went wrong." error page instead of the page I'm telling it to.
Here's my controller function:
public function doRegister() {
$rules = array(
'fname'=>'required|alpha|min:2',
'lname'=>'required|alpha|min:2',
'email'=>'required|email|unique:users',
'company'=>'required|alpha|min:2',
'password'=>'required|alpha_num|between:6,12|confirmed',
'password_confirmation'=>'required|alpha_num|between:6,12'
);
$validator = Validator::make(Input::all(), $rules);
if($validator->passes()) {
User::create(array(
'fname' => Input::get('fname'),
'lname' => Input::get('lname'),
'email' => Input::get('email'),
'password' => Hash.make(Input::get('password')),
'company' => Input::get('company'),
'created_at' => date('Y-m-d H:m:s'),
'updated_at' => date('Y-m-d H:m:s')
));
return Redirect::to('login')->with('message', 'Thank you for registering!');
} else {
return Redirect::to('register')
->with('message', 'The following errors occurred')
->withErrors($validator)
->withInput(Input::except('password'));
}
}
Removing the User::create() section, the redirect works perfectly fine. Just to start with I've included all the database fields in the fillable array in my User model. Still doesn't work. Any ideas?
Not the direct answer to your question, but the quickest way for you to find it.
Open app.php
edit the last line seen in this picture from (in your case) false to true:
Once done that, laravel will tell you what the error is.
One error for sure is
'password' => Hash.make(Input::get('password')),
should be with ::
'password' => Hash::make(Input::get('password')),
You don't need this:
'created_at' => date('Y-m-d H:m:s'),
'updated_at' => date('Y-m-d H:m:s')
laravel will do this for you!
If it doesn't work after this, try to run
php artisan dump-autoload
from your terminal to generate an optimized class loader!