I'm trying to do the Dusk testing.
ViewAnotherUsersTweetsTest.php
/**
* #test
*/
public function can_view_another_users_tweets()
{
$user = factory(User::class)->create(['username' => 'johndoe']);
// make() stores in memory
$tweet = factory(Tweet::class)->make([
'body' => 'My first tweet'
]);
$user->tweets()->save($tweet);
$this->browse(function ($browser) {
$browser->visit('/johndoe')
->dump();
});
}
Route in web.php : Route::get('{username}', 'UserController#show');
UserController.php
class UserController extends Controller
{
public function show(string $username) {
$user = User::findByUsername($username); // ExecuteSolutionController not defined.
dd($user);
}
}
in App\User.php model file
public static function findByUsername($username) {
return self::where('username', $username)->first();
}
When I execute the test with command php artisan dusk --filter can_view_another_users_tweets, it fails and shows following error message.
(1/1) InvalidArgumentException Action Facade\Ignition\Http\Controllers\ExecuteSolutionController not defined.
What could be the reason and how can I fix it?
Related
I've been using backpack in Laravel but I want to replace action-domain-responder architecture with MVC.So I've created an Action which my route refers like below:
Route::get('post',[
'as' => 'post.index',
'uses' => 'Core\Post\Actions\ApiGetListOfPostsAction',
'operation' => 'list'
]);
class ApiGetListOfPostsAction extends BaseAction implements IAction
{
private $service;
public function __construct(ApiGetListOfPostsService $service)
{
$this->service = $service;
}
public function __invoke(Request $request): mixed
{
$data = $this->service->process();
return response()->json($data);
}
}
and my service has this code:
class ApiGetListOfPostsService extends CrudController
{
use ListOperation, CreateOperation, DeleteOperation, UpdateOperation;
public function setup()
{
CRUD::setModel(\App\Models\Post::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/post');
CRUD::setEntityNameStrings('post', 'posts');
}
protected function setupListOperation()
{
CRUD::column('title');
CRUD::column('content');
}
public function process()
{
return $this->index();
}
}
I've extended CrudController in my service class but I've got this error:
Call to a member function hasAccessOrFail() on null
which related to the ListOperation Trait and this code:
public function index()
{
$this->crud->hasAccessOrFail('list');
}
I need to send all requests to the Service class. How can I pass requests to the service class?
When I deleted middleware from CrudController I have no problem.
$this->middleware(function ($request, $next) {
$this->crud = app()->make('crud');
$this->crud->setRequest($request);
$this->setupDefaults();
$this->setup();
$this->setupConfigurationForCurrentOperation();
return $next($request);
});
I think your Action is missing something.
When using inheritance from a parent class, it might help to put this line in your constructor.
public function __construct(ApiGetListOfPostsService $service)
{
parent::__construct(); // <- Subclass constructor
$this->service = $service;
}
Doc: https://www.php.net/manual/en/language.oop5.decon.php
I'm using Laravel 7.
Facing frustrated error,
InvalidArgumentException Action App\Http\Controllers\CMSController#viewCmsPages not defined.
Successful:
redirect('/admin/view-cms-pages')
Fails:
redirect()->action('CMSController#viewCmsPages')
class CmsController extends Controller
{
public function addCmsPage(Request $request)
{
if ($request->isMethod('post')) {
$data = $request->all();
$cmspage->save();
//return redirect('/admin/view-cms-pages')->with('flash_message_success','success');
//why fail...
return redirect()->action('CMSController#viewCmsPages')->with('flash_message_success', 'success');
}
return view('admin.pages.add_cms_page');
}
public function viewCmsPages()
{
return view('admin.pages.view_cms_pages');
}
}
Route::group(['middleware' => ['adminlogin']], function () {
Route::get('/admin/view-cms-pages','CmsController#viewCmsPages');
//i try to add in this resource version also still can't call to
Route::resource('/admin/pages', 'CMSController');
});
When I run php artisan route:list, I can see CMSController#viewCmsPages registered in the list.
Try this on your controller :
return redirect()->route('cms.view')->with('flash_message_success', 'success');
And then add name for the route on web.php :
// Add name for the route
Route::get('/admin/pages', 'CMSController#viewCmsPages')->name ('cms.view');
If you have a custome route, you should register it first, resource route only work for method [index,create,store,show,destory,edit,update]
I was trying to make tests for my auth routes. For password reset route I am trying to make in which I am faking the notification module of laravel and asserting as per the docs.
This is my test file
public function testUserReceivesAnEmailWithAPasswordResetLink()
{
$this->withoutExceptionHandling();
Notification::fake();
$user = factory(User::class)->make();
$response = $this->post($this->passwordEmailPostRoute(), [
'email' => $user->email,
]);
$this->assertNotNull($token = DB::table('password_resets')->where('email', $user->email));
Notification::assertSentTo($user, PasswordReset::class);
}
While I am running this, I am getting notification was not sent error.
My User model is like this:
use Notifiable, HasApiTokens, SoftDeletes, Uuidable, Switchable, ResourceMapper;
public function role()
{
return $this->belongsTo('App\Models\Role');
}
public function company()
{
return $this->belongsTo('App\Models\Company');
}
public function AauthAccessToken()
{
return $this->hasMany('App\Models\OauthAccessToken');
}
public function isRole($role)
{
return $this->role->uuid == $role;
}
public function sendPasswordResetNotification($token)
{
$this->notify(new PasswordReset($token));
}
public function resource()
{
return $this->morphTo();
}
I can't figure whats the exact problem.
i would like to write a test for my custom rules.
my example looks like this.
I'm check if the user gives the correct current password.
my custom rule:
public function passes($attribute, $value)
{
return Hash::check($value, auth()->user()->password);
}
public function message()
{
return 'Your current password is incorrect.';
}
and the test for this rule:
class CurrentPasswordTest extends TestCase
{
use WithFaker, RefreshDatabase;
/** #test */
public function current_password_must_be_valid()
{
$rule = new CurrentPassword();
$user = factory(User::class)->create(['password' => '1234']);
$this->assertTrue($rule->passes('current_password','1234'), $user->password);
}
}
but i'm getting an error:
Tests\Unit\CurrentPasswordTest::current_password_must_be_valid
ErrorException: Trying to get property 'password' of non-object
what i'm doing wrong in this example ?
You need to log in your user before you can use your passes() method - otherwise auth()->user() will be null. You can do that using the be($user) method like this:
/** #test */
public function current_password_must_be_valid()
{
$rule = new CurrentPassword();
$user = factory(User::class)->create(['password' => '1234']);
$this->be($user);
$this->assertTrue($rule->passes('current_password','1234'), $user->password);
}
It would also be advisable to guard against null values in your passes() method to prevent errors. If there is no user logged in, it should probably just return false.
show error : Missing argument 1 for App\Http\Controllers\AdminLoginController::name()
public function name($username) {
$user = AdminLogin::find($username);
return response()->json($user);
}
AdminLoginController: Its a adminlogin controller code
class AdminLoginController extends Controller{
public function show(){
$res ="Hello world!";
return response()->json($res);
}
public function log() {
$users = AdminLogin::all();
return response()->json($users);
}
public function name($username) {
$user = AdminLogin::where('username',$username)->first();
return response()->json($user);
}
RouteLoginController: Its a adminlogin controller code :
<?php
$app->get('/', function () use ($app) {
return $app->version();
});
$app->group(['prefix' => 'api/v1'], function ($app)
{
$app->get('adminlogin', 'AdminLoginController#show'); //get single route
$app->get('user', 'AdminLoginController#log'); //get single route
$app->get('username', 'AdminLoginController#name'); //get single route
$app->post('adminlogin', 'AdminLoginController#login'); //get single route
});
Error :
(1/1) ErrorException
Missing argument 1 for App\Http\Controllers\AdminLoginController::name()
Your controller method is taking the username param but the route binding is not passing one. Change your route
$app->get('username', 'AdminLoginController#name');
to
$app->get('user/{username}', 'AdminLoginController#name');
If you don't want to change your route, change your controller function signature to the below (as shown in the other answers), and make sure you are passing the 'username' as request param while invoking the url.
public function name(\Illuminate\Http\Request $request) {
$user = AdminLogin::where('username',$request->username)->first();
return response()->json(['user' => $user]);
}
You are probably calling this function using an ajax request and putting the name in the query string. In this case, the name parameter will not be sent as an attribute of the function but will be part of the request object.
You can solve this like so:
public function name(\Illuminate\Http\Request $request) {
$user = AdminLogin::find($request->username);
return response()->json($user);
}
You should try this :
public function name($username) {
$user = AdminLogin::where('username',$username)->first();
return response()->json(['user' => $user]);
}
OR
public function name(\Illuminate\Http\Request $request) {
$user = AdminLogin::where('username',$request->username)->first();
return response()->json(['user' => $user]);
}