I try to use PhpUnit with Laravel 5.2.
When I run this test:
class TestInscription extends TestCase
{
/******************************************************************************/
/* pour lancer le test : C:\wamp\www\compet>phpunit tests/TestInscription.php */
/******************************************************************************/
function __construct()
{
parent::setUp();
}
public function testInscriptionAvecErreur()
{
$this->visit('inscription')
->seePageIs('inscription')
->see('Inscription')
->type('', 'nom')
->type('', 'prenom')
->type('', 'email')
->type('', 'password')
->type('', 'password_confirm')
->press('bouton_valider')
->seePageIs('inscription')
->see('Nom obligatoire')
->see('Prénom obligatoire')
->see('Adresse email obligatoire')
->see('Mot de passe obligatoire');
}
I have a response "OK".
When I add a second test into the same class, like this :
class TestInscription extends TestCase
{
/******************************************************************************/
/* pour lancer le test : C:\wamp\www\compet>phpunit tests/TestInscription.php */
/******************************************************************************/
function __construct()
{
parent::setUp();
}
public function testInscriptionAvecErreur()
{
$this->visit('inscription')
->seePageIs('inscription')
->see('Inscription')
->type('', 'nom')
->type('', 'prenom')
->type('', 'email')
->type('', 'password')
->type('', 'password_confirm')
->press('bouton_valider')
->seePageIs('inscription')
->see('Nom obligatoire')
->see('Prénom obligatoire')
->see('Adresse email obligatoire')
->see('Mot de passe obligatoire');
}
public function testInscriptionAvecErreurMdp()
{
$this->visit('inscription')
->seePageIs('inscription')
->see('Inscription')
->type('azerty', 'password')
->type('azertyu', 'password_confirm')
->press('bouton_valider')
->seePageIs('inscription')
->see('Les 2 mots de passe sont différents');
}
}
then I have an error on the first test (the second one is not triggered). The error is:
Time: 2.69 seconds, Memory: 20.50MB
There was 1 failure:
1) TestInscription::testInscriptionAvecErreur
A request to [http://localhost/inscription] failed. Received status code [500].
C:\wamp\www\compet\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:196
C:\wamp\www\compet\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:80
C:\wamp\www\compet\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:61
C:\wamp\www\compet\tests\TestInscription.php:21
C:\wamp\www\ecole\vendor\phpunit\phpunit\src\TextUI\Command.php:149
C:\wamp\www\ecole\vendor\phpunit\phpunit\src\TextUI\Command.php:100
Caused by
exception 'ErrorException' with message 'Undefined variable: errors' in C:\wamp\www\compet\storage\framework\views\7a56ba5973bcafaa00c3a5edb3816871f0ac8a17.php:44
I see in this view:
<div class="form-group <?php echo e($errors->has('nom') ? 'has-error has-feedback' : ''); ?>">
Certainly the error is because this variable "$errors", but what?
and why the first test runs fine when it is alone. And fails when I add a second test?
I found the error (but don't know if it is the real reason).
When I create several functions into my class, then I have the error. When I create only 1 function into my class, then I have no errors.
So I decided to create only 1 function per test class (even if the function can be very long).
Related
I can't get out of this error: Object of class Symfony\Bridge\Twig\Mime\WrappedTemplatedEmail could not be converted to string
My setup :
php 8.2
symfony 6.2
mailer 6.2
and i use maildev
I would like to generate a mail sending with ajax.
My service :
<?php
namespace App\Service;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Mailer\MailerInterface;
class SendMailService
{
private $mailer;
public function __construct(MailerInterface $mailer)
{
$this->mailer = $mailer;
}
public function send(string $from, string $to, string $subject, string $template, array $context): void
{
$email = (new TemplatedEmail())
->from($from)
->to($to)
->subject($subject)
->htmlTemplate("emails/$template.html.twig")
->context($context);
// On envoie le mail
$this->mailer->send($email);
}
}
if I put ->context([$context]) instead of ->context($context), in my template I get this error: there is no variable 'prenom'
My controller action :
#[Route('/app_email', name: 'app_email', methods: ['POST'])]
public function sendEmail(Request $request, SendMailService $mail): Response
{
if ($request->isXmlHttpRequest()) {
$from = $this->getParameter('from_email');
$emailAdressTo = $request->request->get('email'); // To
$template = 'contact';
$subject = "Envoi à partir du formulaire de contact du site Vous assurance";
$nom = $request->request->get('nom');
$prenom = $request->request->get('prenom');
$entreprise = $request->request->get('entreprise');
$message = $request->request->get('message');
$context = array(
'nom' => $nom,
'prenom' => $prenom,
'entreprise' => $entreprise,
'message' => $message,
);
dump($from);
dump($emailAdressTo);
dump($subject);
dump($template);
dump(gettype($context));
$mail->send($from, $emailAdressTo, $subject, $template, $context);
return new Response("ok");
}
return new Response("Erreur : ceci n'est pas une requête ajax", 400);
}
Dump result :
Dumped Contents In MainController.php line 54: "xxxx#xxx.fr" In MainController.php line 55: "xxxxx#xxxxx.com" In MainController.php line 56: "Envoi à partir du formulaire de contact du site" In MainController.php line 57: "contact" In MainController.php line 58: "array"
if I comment out the $context variable, my email is sent
My ajax function :
var formNewContact = $('form[id="formContact"]');
formNewContact.on("submit", function (e) {
e.preventDefault();
var formData = new FormData($(this)[0]);
$.ajax({
method: "POST",
url: "{{ path('app_email') }}",
data: formData,
processData: false,
contentType: false,
success: function (response) {
if (response === 'ok') {
} else {
alert("Erreur");
}
}, // Fin success
error: function () {
alert("Erreur serveur");
}, // Fin error
}); // Fin ajax
}); // Fin function submit form contact
My template :
<p>Bonjour,</p>
<p><strong>De : </strong>{{ prenom }}<strong>{{ nom }}</strong>.</p>
<p><strong>Email : </strong>{{ email }}</p>
<p><strong>Entreprise : </strong>{{ entreprise }}</p>
<p><strong>Message :</strong></p>
<hr />
<p>{{message}}</p>
<hr />
</div>
dump(gettype($context)); -> array
Thanks for your help.
I changed :
In form this field :
<div class="mb-3">
<label for="emailTo" class="form-label">Mail (obligatoire)</label>
<input type="email" class="form-control" name="emailTo" id="emailTo" aria-describedby="mailHelp" pattern="[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$" required>
<div class="valid-feedback feedback-pos">
Adresse email OK
</div>
<div class="invalid-feedback feedback-pos">
Cette adresse email n'est pas correcte
</div>
</div>
In your template, you are trying to render the email instance as a string with {{ email }}. That's why you get this error.
Maybe you want to print the email address instead : {{ email.to[0].address }}
See : https://symfony.com/doc/current/mailer.html#html-content
The Twig template has access to any of the parameters passed in the context() method of the TemplatedEmail class and also to a special variable called email, which is an instance of WrappedTemplatedEmail.
I struggle to send a mail inside a botman reply.
I use mailhog, with botman 2.0 and laravel 5.7.
I've tested mailhog with simple php code , it work.
Here my env file config :
MAIL_DRIVER=smtp
MAIL_HOST=localhost
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
The conversation start here :
<?php
namespace App\Conversations\SASI\CreationTicket;
//use Validator;
use Illuminate\Support\Facades\Validator;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Conversations\Conversation;
use App\Conversations\SASI\CreationTicket\EndTicketResume;
class EndTicket extends Conversation
{
public function askProblem()
{
$this->ask('Décrivez succintement votre problème :', function(Answer $answer) {
$this->bot->userStorage()->save([
'problem' => $answer->getText(),
]);
$this->askEmail(); //passe à la fonction suivante
});
}
public function askEmail()
{
$this->ask('Quel est votre email?', function(Answer $answer) {
$validator = Validator::make(['email' => $answer->getText()], [
'email' => 'email',
]);
if ($validator->fails()) {
return $this->repeat('Cette email ne semble pas valide. Entrez un email valide.');
}
$this->bot->userStorage()->save([
'email' => $answer->getText(),
]);
$this->askMobile();
});
}
public function askMobile()
{
$this->ask('Quel est votre numéro pro?', function(Answer $answer) {
$this->bot->userStorage()->save([
'mobile' => $answer->getText(),
]);
$this->say('Merci');
//renvoi a une autre conversation app\Conversations\SelectServiceConversation.php
$this->bot->startConversation(new EndTicketResume());
});
}
public function run()
{
$this->askProblem();
}
}
As you can see the bot say "Merci" (thanks) and go to another conversation. If add my mail code the bot stop before he say "Merci"
So the next conversation :
<?php
namespace App\Conversations\SASI\CreationTicket;
use Illuminate\Support\Facades\Mail;
use BotMan\BotMan\Messages\Conversations\Conversation;
class EndTicketResume extends Conversation
{
public function confirmTicket()
{
$user = $this->bot->userStorage()->find();
$message = '------------------------------------------------ <br>';
$message .= 'Probleme : '.$user->get('problem').'<br>';
$message .= 'Email : '.$user->get('email').'<br>';
$message .= 'Tel : '.$user->get('mobile').'<br>';
$message .= '------------------------------------------------';
$this->say('Votre demande va être envoyé. <br><br>'.$message);
$email = $user->get('email');
$data = [
'first' => 'test',
'last' => 'TEST'
];
// send email with details
Mail::send('emails.justshoot', $data, function($message) use ($email) {
$message->subject('Welcome');
$message->from($email, 'Just Shoot Upload');
$message->to('myemail#gmail.com')->cc('test#gmail.com');
});
}
/**
* Start the conversation.
*
* #return mixed
*/
public function run()
{
$this->confirmTicket();
}
}
If I remove this
Mail::send('emails.justshoot', $data, function($message) use ($email) {
$message->subject('Welcome');
$message->from($email, 'Just Shoot Upload');
$message->to('myemail#gmail.com')->cc('test#gmail.com');
});
The bot say his last message, all is ok. But if I add this code , as I said previously, the bot won't even go to another conversation.
What I am doing wrong ?
Try to put the mail in a seperate function and different controller
you can debug using network tab in the console
With laravel 7 /livewire app I make crud using Repository and I got listing of data ok,
In mount event I assign protected var $FacilityRepository , which works ok in render method,
but it is null in edit method and I got error:
Call to a member function getById() on null
when user clicks on “edit link”
<?php
namespace App\Http\Livewire\Admin;
use App\library\CheckValueType;
use App\Settings;
use DB;
use Livewire\Component;
use App\Facility;
use Livewire\WithPagination;
use App\Repositories\Interfaces\FacilityRepositoryInterface;
class Facilities extends Component
{
use WithPagination;
public $form= [
'name'=>'',
'descr'=> '',
'created_at'=> '',
'is_reopen' => false,
];
public $current_facility_id;
public $filter_name= '';
public $updateMode = 'browse';
protected $FacilityRepository;
public function render()
{
$this->facility_rows_count = Facility
::getByName($this->filter_name, true)
->count();
$backend_per_page = Settings::getValue('backend_per_page', CheckValueType::cvtInteger, 20);
\Log::info( 'render -10 $this->FacilityRepository::' . print_r( json_encode($this->FacilityRepository), true ) );
// line above logged as : [2020-09-04 16:46:26] local.INFO: render -10 $this->FacilityRepository::{}
return view('livewire.admin.facilities.container', [
'facilityDataRows' => $this->FacilityRepository->filterWithPagination(
[
'name'=>$this->filter_name,
],
$backend_per_page
),
'facility_rows_count'=> $this->facility_rows_count
]); // this listing is rendered OK
}
public function mount( FacilityRepositoryInterface $FacilityRepository ) {
$this->FacilityRepository = $FacilityRepository;
\Log::info( '-101mount $this->FacilityRepository::' . print_r( json_encode($this->FacilityRepository), true ) );
// line above logged as : [2020-09-04 16:46:26] local.INFO: -101mount $this->FacilityRepository::{}
}
public function edit($id)
{
\Log::info( '-1 edit $id::' . print_r( json_encode( $id ), true ) );
\Log::info( '-1 edit $this->FacilityRepository::' . print_r( $this->FacilityRepository, true ) );
// line above logged as : [2020-09-04 16:46:28] local.INFO: -1 edit $this->FacilityRepository::
// AND ERROR NEXT
$this->form = $this->FacilityRepository->getById($id)->toArray();
\Log::info( '-1023 $this->form ::' . print_r( json_encode( $this->form ), true ) );
$this->current_facility_id = $id;
$this->form['created_at'] = getCFFormattedDateTime($this->form['created_at']);
$this->emit('facility_opened',[ 'mode'=>'edit', 'id'=>$id ]);
$this->updateMode = 'edit';
}
In template edit link is defined as :
#foreach($facilityDataRows as $nextFacilityDataRow)
<tr>
<td class="text-right m-0">
<a wire:click="edit({{$nextFacilityDataRow->id}})"
class="p-1 a_edit_item_{{$nextFacilityDataRow->id}} a_link">
{{$nextFacilityDataRow->id}}
</a>
</td>
...
Why error and how to fix it ?
Modified # 2:
If I make
class Facilities extends Component
{
...
public $FacilityRepository;
}
I got error :
Livewire component's [admin.facilities] public property [FacilityRepository] must be of type: [numeric, string, array, null, or boolean]. Only protected or private properties can be set as other types because JavaScript doesn't need to access them.
I tried to declare method edit as :
public function edit( FacilityRepositoryInterface $facilityRepository, int $id)
{ // Did you mean this ?
...
}
I got error :
Call to a member function filterWithPagination() on null
on method filterWithPagination, which is used in render method, when I show listing of data.
Which way is correct ?
Modified # 3:
If to modify :
public function render(FacilityRepositoryInterface $facilityRepository)
{
I got error :
Declaration of App\Http\Livewire\Admin\Facilities::render(App\Repositories\Interfaces\FacilityRepositoryInterface $facilityRepository) should be compatible with Livewire\Component::render()
?
Modified # 4:
Opening page in mode I have 2 inputs with lazy defined, like
<dd class="horiz_divider_right_23" wire:model="form.title.lazy" x-data="{ name: '{{$form['name']}}'}">
<input
x-model="name"
x-on:blur="$dispatch('name', name)"
id="name"
class="form-control editable_field admin_control_input"
placeholder="Enter descriptive name"
autocomplete=off
>
#error('form.name')
<div class="validation_error">{{ clearValidationError($message,['form.'=>'']) }}</div> #enderror
</dd>
and when I edit some of fields on blur ervent I got the same error :
Call to a member function filterWithPagination() on null
with url in error description :
VM5783:1 POST http://local-hostels3.com/livewire/message/admin.facilities 500 (Internal Server Error)
where http://local-hostels3.com is my local hosting
Have I in some way to overrride message method ?
"laravel/framework": "^7.0",
"livewire/livewire": "^1.3",
Thanks!
protected and private properties DO NOT persist between Livewire updates. In general, you should avoid using them for storing state.
https://laravel-livewire.com/docs/properties/#important-notes
That being said, you can use dependency injection again, just pass whatever you need (FacilityRepositoryInterface in this case) as the first argument(s) of the edit method.
Same applies to the render method, so you can skip mount altogether.
Correction
The last bit in my original answer is wrong, you cannot use DI in the render method.
So for use in render, use the mount method and for use in edit, bring it via the first parameter. If render complains about not having it after usage of edit, save to the protected property inside edit as well.
Final code, that should work
class Facilities extends Component
{
protected $FacilityRepository;
public function mount(FacilityRepositoryInterface $FacilityRepository)
{
$this->FacilityRepository = $FacilityRepository;
}
public function render()
{
// use $this->FacilityRepository->...
}
public function edit(FacilityRepositoryInterface $FacilityRepository, $id)
{
$this->FacilityRepository = $FacilityRepository;
// rest of the edit method from your code
}
}
add boot method
public function boot(FacilityRepositoryInterface $FacilityRepository)
{
$this->FacilityRepository = $FacilityRepository;
}
I am trying to insert the data in database while using Laravel. I am getting the error
BadMethodCallException Call to undefined method
App\AskQuestion::email()
While create.blade.php is my view and respones is the name of my table. The controller name is ResponesContoller and its code is given.
public function create()
{
abort_if(Gate::denies('respone_create'), Response::HTTP_FORBIDDEN, '403 Forbidden');
$categories = Category::all()->pluck('name', 'id')->prepend(trans('Sélectionnez la thématique'), '');
$author_emails = User::all()->pluck('email', 'id')->prepend(trans('Choisissez votre email'), '');
$ask_questions = AskQuestion::all();
return view('admin.respones.create', compact('categories', 'author_emails', 'ask_questions'));
}
public function store(StoreResponeRequest $request)
{
$respone = Respone::create($request->all());
return redirect()->route('admin.respones.index')->with('success', 'Réponse enregistrée avec succès!');
}
public function edit(Respone $respone)
{
abort_if(Gate::denies('respone_edit'), Response::HTTP_FORBIDDEN, '403 Forbidden');
$categories = Category::all()->pluck('name', 'id')->prepend(trans('Sélectonnez la thématique'), '');
$author_emails = User::all()->pluck('email', 'id')->prepend(trans('Choisissez votre email'), '');
$ask_questions = AskQuestion::all()->pluck('text_question', 'id')->prepend(trans('Choisissez la question posée'), '');
$respone->load('category', 'author_email', 'ask_question');
return view('admin.respones.edit', compact('categories', 'author_emails', 'ask_questions', 'respone'));
}
The code of web.php is given and it works correctly, before I have checked as a test.
Please if anyone can help me!
Here was the problem i solve it.
public function created(Respone $model)
{
$data = ['action' => 'Une réponse est apportée à votre question!', 'model_name' => 'Respone',
'respone' => $model ];
$askQuestions = \App\AskQuestion::WhereHas('respones', function($q) {
return $q->where('objet_question', 'email', 'text_question');
})->get();
Notification::send($askQuestions, new ResponeEmailNotification($data));
}
I'm implementing roles and permission for a project, and using policies, but I have a problem when I want to authorize or not the creation of new records in the patients table, very simple stuff.
I have this in my PatientPolicy
// Only the users with root or admin roles can create patients;
public function create(User $user){
return ($user->hasRole('root') || $user->hasRole('admin'));
}
// only the patient creator can edit the patient and see the edit button
public function update(User $user, Patient $patient){
return $user->id == $patient->user_id;
}
AuthServiceProvider
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
'App\Patient' => 'App\Policies\PatientPolicy'
];
PatientController
public function edit(Patient $patient){
if(Gate::denies('update', $patient)){
abort(403, 'No esta autorizado de estar aqui');
}
return view('patients.edit', compact('patient'));
}
public function create(){
if(Gate::denies('create')){
abort(403, 'Usted no esta autorizado para crear pacientes');
}
return view('patients.create');
}
and in my views
#can('create')
<li class="header">PROCESOS</li>
<li><i class="fa fa-book"></i> <span>Apertura de Historia Clínica</span></li>
#endcan
The problem is that the create policy is always returning false even for those users that are suppossed to be allowed to perform the action, however the edit policy works perfectly. Am I missing something?
The problem is Gate::denies and #can methods don't know which model and policy class they should look for when there is no argument to correspond, so use this code instead:
public function create(){
if(Gate::denies('create', Patient::class)) {
abort(403, 'Usted no esta autorizado para crear pacientes');
}
return view('patients.create');
}
and in your views:
#can('create', App\Patient::class)
<li class="header">PROCESOS</li>
<li><i class="fa fa-book"></i> <span>Apertura de Historia Clínica</span></li>
#endcan
You can check my full answer here:
https://stackoverflow.com/a/37261276/3477084