Why laravel assertions are not called from closure? - laravel

My code is:
public function testOne()
{
$mail = ['subject' => 'My subject'];
$this->assertEquals(1, 1);
$mock = Mockery::mock(\Illuminate\Support\Facades\Mail::getSwiftMailer());
$this->app['mailer']->setSwiftMailer($mock);
$msg = $mock->shouldReceive('send')->once()->andReturnUsing(function($msg) {
echo $msg->getSubject();
$this->assertEquals($mail['subject'], $msg->getSubject());
});
$this->assertEquals(1, 1);
}
I get output:
PHPUnit 4.8.24 by Sebastian Bergmann and contributors.
My subject
Time: 852 ms, Memory: 26.00Mb
OK (1 test, 2 assertions)
I see from output:
echo $msg->getSubject();
that I get good subject but nothing is asserted, why?

Use like this
public function testOne()
{
$mail = ['subject' => 'My subject'];
$this->assertEquals(1, 1);
$mock = Mockery::mock(\Illuminate\Support\Facades\Mail::getSwiftMailer());
$this->app['mailer']->setSwiftMailer($mock);
$obj = $this;
$msg = $mock->shouldReceive('send')->once()->andReturnUsing(function($msg) use ($obj, $mail) {
echo $msg->getSubject();
$obj->assertEquals($mail['subject'], $msg->getSubject());
});
$this->assertEquals(1, 1);
}
Inside your closure it's an instance of Closure so it will not get $this from there for that you have to assign to another variable & use it.
But you can rewrite your tests like this
public function testOne()
{
$mail = ['subject' => 'My subject'];
$this->assertEquals(1, 1);
$mock = Mockery::mock(\Illuminate\Support\Facades\Mail::getSwiftMailer());
$this->app['mailer']->setSwiftMailer($mock);
$message = null;
$mock->shouldReceive('send')->once()->andReturnUsing(function($msg) use ($message) {
$message = $msg->getSubject();
});
$this->assertEquals($mail['subject'], $message);
$this->assertEquals(1, 1);
}

Related

Laravel - POSTMAN Login Internal Server Error

I am using Laravel-5.8 as backend for an application. I have written all the Api for the endpoints.
Laravel: ApiController
protected function guard()
{
return Auth::guard();
}
public function returnResponse($success, $data, $errorCode = 0, $message = false) {
$response = array();
$response['success'] = $success;
$response['message'] = isset($message) ? $message : '';
if ($errorCode) {
$response['errorCode'] = isset($errorCode) ? $errorCode : 0;
}
$response['data'] = $data;
return response()->json($response, 200);
}
public function login() {
$authenticated = false;
$remember = request('remember') ? true : false;
if (Auth::guard('web')->attempt(['email' => request('email'), 'password' => request('password')], $remember)) {
$authenticated = true;
}
if ($authenticated == true) {
$user = Auth::guard('web')->user();
$date = date('Y-m-d');
$success['userId'] = $user->id;
$success['avatar'] = url('/storage/user') . '/' . $user->avatar;
// $success['points'] = $user->userPoints->sum('points');
$success['email'] = $user->email;
$success['token'] = $user->createToken('MyApp')->accessToken;
return $this->returnResponse(true, $success);
} else {
$success = array();
return $this->returnResponse(false, $success, 1, 'Invalid User Credential');
}
}
api.php
Route::group([
], function () {
Route::post('login', 'ApiController#login');
Route::post('register', 'ApiController#register');
Route::post('forgetPassword', 'ApiController#forgetPassword');
Route::group([
'middleware' => 'auth:api'
], function() {
Route::get('logout', 'AuthController#logout');
Route::get('user', 'AuthController#user');
});
});
When I test the login Post Request on the POSTMAN, I got the error shown below:
What could have caused the error?
i think you have declare index() multiple times in your controller so please check and if there is multiple times declaration of index() then just remove anyone.

Object of class Illuminate\Routing\Redirector could not be converted to string. srmklive/laravel-paypal

I am currently working on a paypal checkout using paypal and https://github.com/srmklive/laravel-paypal. I'm using the express checkout which I modified it a little bit to fit the requirements of the my project. During testing it is working in a couple of tries, paypal show and payment executes properly but when I tried to run the exact same code. I get this error I don't know what it means.
I tried to check my routes if it all of the errors happens to my routes but all of it are working properly. I also tried dump and die like dd("check") just to check if its really going to my controller and it does. I did this in the method "payCommission" (this where the I think the error happens)
This is my route for the controller
api.php
Route::get('service/commissionfee/payment' , 'api\service\ExpressPaymentController#payCommission');
Route::get('paypal/ec-checkout-success', 'api\service\ExpressPaymentController#payCommissionSuccess');
ExpressPaymentController.php
<?php
namespace App\Http\Controllers\api\service;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Srmklive\PayPal\Services\ExpressCheckout;
class ExpressPaymentController extends Controller
{
protected $provider;
public function __construct()
{
try {
$this->provider = new ExpressCheckout();
}
catch(\Exception $e){
dd($e);
}
}
public function payCommission(Request $request)
{
$recurring = false;
$cart = $this->getCheckoutData($recurring);
try {
$response = $this->provider->setExpressCheckout($cart, $recurring);
return redirect($response['paypal_link']);
} catch (\Exception $e) {
dd($e);
return response()->json(['code' => 'danger', 'message' => "Error processing PayPal payment"]);
}
}
public function payCommissionSuccess(Request $request)
{
$recurring = false;
$token = $request->get('token');
$PayerID = $request->get('PayerID');
$cart = $this->getCheckoutData($recurring);
// ? Verify Express Checkout Token
$response = $this->provider->getExpressCheckoutDetails($token);
if (in_array(strtoupper($response['ACK']), ['SUCCESS', 'SUCCESSWITHWARNING'])) {
if ($recurring === true) {
$response = $this->provider->createMonthlySubscription($response['TOKEN'], 9.99, $cart['subscription_desc']);
if (!empty($response['PROFILESTATUS']) && in_array($response['PROFILESTATUS'], ['ActiveProfile', 'PendingProfile'])) {
$status = 'Processed';
} else {
$status = 'Invalid';
}
} else {
// ? Perform transaction on PayPal
$payment_status = $this->provider->doExpressCheckoutPayment($cart, $token, $PayerID);
$status = $payment_status['PAYMENTINFO_0_PAYMENTSTATUS'];
}
return response()->json(['success' => "payment complete"]);
}
}
private function getCheckoutData($recurring = false)
{
$data = [];
$order_id = 1;
$data['items'] = [
[
'name' => 'Product 1',
'price' => 9.99,
'qty' => 1,
],
];
$data['return_url'] = url('api/paypal/ec-checkout-success');
// !
$data['invoice_id'] = config('paypal.invoice_prefix').'_'.$order_id;
$data['invoice_description'] = "Commission Fee payment";
$data['cancel_url'] = url('/');
$total = 0;
foreach ($data['items'] as $item) {
$total += $item['price'] * $item['qty'];
}
$data['total'] = $total;
return $data;
}
}
Error I am getting
Object of class Illuminate\Routing\Redirector could not be converted to string
Thank you in advance
you may just go to the config/paypal.php and edit
'invoice_prefix' => env('PAYPAL_INVOICE_PREFIX', 'Life_saver_'),
you may use _ underline in this like Life_saver_, dont forget use underline at the end too.

Cannot Update On Laravel 5.5

I get problem.
This is my controller
public function finish(Request $request)
{
$result = $request->input('data');
//$data = json_decode($result, true);
return $this->InvoiceBayar($result);
}
public function InvoiceBayar($result)
{
$data = json_decode($result, true);
$transaction = $data['transaction_status'];
$type = $data['payment_type'];
$order_id = $data['order_id'];
$fraud = $data['fraud_status'];
Fee::where('invoice',$order_id)
->update([
'status' => 'Paid',
]);
echo "Transaction order_id: " . $order_id ." successfully transfered using " . $type;
}
This is my Route
Route::POST('/notification', 'SnapController#finish');
When Payment gateway, send a parameter to me, I cannot update DB.
But when I use POSTMAN. I success update DB
You need to use $request->all() as it will contain all payment gateway data.
public function finish(Request $request)
{
$result = $request->all();
return $this->InvoiceBayar($result);
}
Alternately you can do this
$update = Fee::where('invoice',$order_id)->first();
$update->status = 'Paid';
$update->save();
You should try this:
public function InvoiceBayar($result)
{
$data = json_decode($result, true);
$transaction = $data->transaction_status;
$type = $data->payment_type;
$order_id = $data->order_id;
$fraud = $data->fraud_status;
Fee::where('invoice',$order_id)
->update([
'status' => 'Paid',
]);
echo "Transaction order_id: " . $order_id ." successfully transfered using " . $type;
}

How to call shell function to another Controller - Cakephp

I'm using this function in my shell to send email
Edit :
UsersShell
<?php
namespace App\Shell;
use Cake\Console\Shell;
use Cake\Log\Log;
use Cake\Controller\Component;
use Cake\Controller\ComponentRegistry;
use App\Controller\Component\EmailComponent;
class UsersShell extends Shell
{
public function initialize()
{
parent::initialize();
$this->loadModel('Users');
//Load Component
$this->Email = new EmailComponent(new ComponentRegistry());
}
public function mail()
{
$to = 'exemple#gmail.com';
$subject = 'Hi buddy, i got a message for you.';
$message = 'User created new event';
try {
$mail = $this->Email->send_mail($to, $subject, $message);
print_r($mail);
} catch (Exception $e) {
echo 'Message could not be sent. Mailer Error: ', $mail-
>ErrorInfo;
}
exit;
}
I would like to know how can I call it in my controller ? here
Edit : Events is located in the plugins folder
EventsController
<?php
namespace FullCalendar\Controller;
use FullCalendar\Controller\FullCalendarAppController;
use Cake\Routing\Router;
use Cake\Event\Event;
use Cake\Console\ShellDispatcher;
class EventsController extends FullCalendarAppController
{
public $name = 'Events';
public function add()
{
$event = $this->Events->newEntity();
if ($this->request->is('post')) {
$event = $this->Events->patchEntity($event, $this->request->data);
if ($this->Events->save($event)) {
/* $shell = new ShellDispatcher();
$output = $shell->run(['cake', 'users'], ['plugin' =>
'Events']);
if (0 === $output) {
$this->Flash->success('Success from shell command.');
} else {
$this->Flash->error('Failure from shell command.'); */
$this->Flash->success(__('The event has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The event could not be saved. Please,
try again.'));
}
}
$this->set('eventTypes', $this->Events->EventTypes->find('list'));
$this->set(compact('event'));
$this->set('_serialize', ['event']);
$this->set('user_session', $this->request->session()-
>read('Auth.User'));
$this->viewBuilder()->setLayout('user');
}
As you can see i used the shell dispatched i'm not sure if it's correct
but i'm getting failure
Thanks !
Edit :
EmailComponent
<?php
namespace App\Controller\Component;
use Cake\Controller\Component;
use Cake\Core\App;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require ROOT. '/vendor/phpmailer/phpmailer/src/Exception.php';
require ROOT. '/vendor/phpmailer/phpmailer/src/PHPMailer.php';
require ROOT. '/vendor/phpmailer/phpmailer/src/SMTP.php';
class EmailComponent extends Component {
public function send_mail($to, $subject, $message)
{
// date_default_timezone_set('Asia/Calcutta');
$sender = "exemple#gmail.com"; // this will be overwritten by GMail
$header = "X-Mailer: PHP/".phpversion() . "Return-Path: $sender";
$mail = new PHPMailer();
$mail->SMTPDebug = 2; // turn it off in production
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = "exemple#gmail.com";
$mail->Password = "xxxx";
$mail->SMTPSecure = "tls"; // ssl and tls
$mail->Port = 587; // 465 and 587
$mail->SMTPOptions = array (
'tls' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
),
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
$mail->From = $sender;
$mail->FromName = "From Me";
$mail->AddAddress($to);
$mail->isHTML(true);
$mail->CreateHeader($header);
$mail->Subject = $subject;
$mail->Body = nl2br($message);
$mail->AltBody = nl2br($message);
// return an array with two keys: error & message
if(!$mail->Send()) {
return array('error' => true, 'message' => 'Mailer Error: ' . $mail->ErrorInfo);
} else {
return array('error' => false, 'message' => "Message sent!");
}
}
}
Correct me if I'm wrong. First your shell must be started something like this.
class UsersShell extends AppShell {
public function main(){ //change name here to main
$to = 'exemple#gmail.com';
$subject = 'Hi buddy, i got a message for you.';
$message = 'User created new event';
try {
$mail = $this->Email->send_mail($to, $subject, $message);
print_r($mail);
} catch (Exception $e) {
echo 'Message could not be sent. Mailer Error: ', $mail->ErrorInfo;
}
exit;
}
}
By the way, if you want to check output, you must return something like true or false. Otherwise, there is no point to check output after execute the shell.
First Check Shell Command Run in CakePHP-CLI. Like this
bin/cake users mail
if shell command successfully running. Shell Class Fine.
Next Use Shell in Controller
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Console\ShellDispatcher;
class PagesController extends AppController
{
/**
* Run shell command
*/
public function run()
{
$shell = new ShellDispatcher();
$output = $shell->run(['cake', 'users', 'mail']);
// $output = $shell->run(['cake', 'users', 'mail', 'email']); // [pass arguments]
// debug($output);
if ($output === 0) {
echo "Shell Command execute";
} else {
echo "Failure form shell command";
}
exit;
}
}
Change Shell Function : if mail not sent run $this->abort() function and return (int) 1 and mail sent successfully run $this->out() function and return (int) 0
/**
* Send Mail with shell command
*/
public function mail()
{
$to = 'mail#gmail.com';
$subject = 'Hi buddy, i got a message for you.';
$message = 'Nothing much. Just test out my Email Component using PHPMailer.';
$mail = $this->Email->send_mail($to, $subject, $message);
// debug($mail);
if ($mail['error'] === false) {
$this->out("Mail Successfully Sent For :: ". $to);
} else {
$this->abort("Mail Error.");
}
}

Laravel : API response with pagination parameter

I want to pass pagination parameters through POSTMAN and pass sort,order,limits in my model to get query with paginate.? how can i do this? Currently it return error.
Currently my route :
http://localhost:8000/api/allpost
My PostController function :
public function index(Request $request)
{
try {
$allPost = Post::allUserPost();
if($allPost !="" && count($allPost)>0) {
return [
'status_code' => 200,
'message' => "Post retrieved successfully",
'PostDetails' => $allPost,
];
} else {
return response()->json([
'message' => "Post data not found",
'status_code' => 403,
]);
}
} catch (\Exception $ex) {
return response()->json([
'message' => "Internal server error",
'status_code' => 500,
]);
}
}
And my POST model function :
public static function allUserPost(Request $request){
$sort = $this->parameters->sort();
$order = $this->parameters->order();
$limit = $this->parameters->limit();
$userPost = Post::with(['product','categories','user.userDetails'])->whereStatus("Active")->orderBy($sort, $order)->paginate($limit)->get();
$userPost_array = $userPost->toArray();
foreach ($userPost_array as $key => $value) {
# code...
$attributes_arr = array_column($userPost_array[$key]['categories'], 'attribute_id');
$category_ids = Attribute::whereIn("id",$attributes_arr)->pluck('category_id');
$category_ids = array_unique($category_ids->toArray());
$category_details_with_att = Post::getCategoryWithAttributeData($attributes_arr,$category_ids);
unset($userPost_array[$key]["categories"]);
$userPost_array[$key]["categories"] = $category_details_with_att->toArray();
}
return $userPost_array;
}
Currently it returns error
Type error: Too few arguments to function App\Post::allUserPost(), 0 passed in D:\xampp\htdocs\IDM\app\Api\V1\Controllers\Front\PostController.php on line 30 and exactly 1 expected
So how can i pass parameters in postmen and whats the solution for this error?
First change this line to $allPost = Post::allUserPost();
$allPost = Post::allUserPost($request);
and then change this code
$sort = $this->parameters->sort();
$order = $this->parameters->order();
$limit = $this->parameters->limit();
To
$sort = $request->sort;
$order = $request->order;
$limit = $request->limit;
and then you can pass these paramets in a query string like
http://localhost:8000/api/allpost?sort=somesort&order=asc&limit=10
Also chage this line
$userPost = Post::with(['product','categories','user.userDetails'])->whereStatus("Active")->orderBy($sort, $order)->paginate($limit)->get();
to
$userPost = Post::with(['product','categories','user.userDetails'])->whereStatus("Active")->orderBy($sort, $order)->paginate($limit);
You are missing an argument when calling the allUserPost function inside the try block.
It should be
$allPost = Post::allUserPost($request);
and then you can retrieve the parameters from the $request variable.
Just change this line in your code
$allPost = Post::allUserPost($request);
And then in your function, you have to change your request type. And after that you have to do one more change only use paginate() method not with get() method.
public static function allUserPost(Request $request){
$sort = $request->sort;
$order = $request->order;
$limit = $request->limit;
$userPost = Post::with(['product','categories','user.userDetails'])->whereStatus("Active")->orderBy($sort, $order)->paginate($limit);
$userPost_array = $userPost->toArray();
foreach ($userPost_array as $key => $value) {
$attributes_arr = array_column($userPost_array[$key]['categories'], 'attribute_id');
$category_ids = Attribute::whereIn("id",$attributes_arr)->pluck('category_id');
$category_ids = array_unique($category_ids->toArray());
$category_details_with_att = Post::getCategoryWithAttributeData($attributes_arr,$category_ids);
unset($userPost_array[$key]["categories"]);
$userPost_array[$key]["categories"] = $category_details_with_att->toArray();
}
return $userPost_array;
}
I hope this will help you.

Resources