I'm trying to get my head around testing (again) and in particular test a form request with a custom rule. I'm using Laravel 5.5.
My rule needs a variable from the request to compare the field value under validation.
Whilst I can get this to work in the app I can't create the test correctly and pass the values.
Here's the custom rule (stripped down to essential info):
class TicketNumberIsNotUsed implements Rule
{
public function __construct($reservation_id)
{
$this->reservation_id = $reservation_id;
}
public function passes($attribute, $value)
{
$ticket = TicketAudit::where('ticketnumber', '=', $value)->first();
if($ticket) {
return (is_null($ticket->reservation_id) || $ticket->reservation_id == $this->reservation_id ? true : false);
}
return false;
}
public function message()
{
return 'This ticket has already been used for another booking.';
}
}
Here's the form request which uses the custom rule:
class CreateGreenFeeSaleRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return Auth::user()->hasRole('sales');
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'play_date'=>'required',
'am_tee'=>'required',
'howBooked'=>'required',
'ticket'=>[
'required',
'exists:ticket_audits,ticketnumber' ,
new TicketNumberIsNotUsed($this->reservation_id)
] ,
'pay_method'=>'required',
'customer_id'=>'required:exists:customers,id'
];
}
public function messages()
{
return [
'ticket.required' => 'A valid ticket is required',
'ticket.exists' => 'This ticket does not exist',
];
}
}
and here is my test:
class CreateGreenFeeTest extends TestCase
{
protected function setUp()
{
parent::setUp();
}
private function createAttributes()
{
$faker = \Faker\Factory::create();
$attributes = [
'play_date' => $faker->date('d/m/Y'),
'reservation_id' => null,
'am_tee' => $faker->time('H:m a'),
'howBooked' => 'drop in',
'ticket' => 905,
'pay_method' => 'cash',
'customer_id' => 1532
];
return $attributes;
}
public function test_form_validation_passes()
{
$attributes = $this->createAttributes();
$request = new \App\Http\Requests\CreateGreenFeeSaleRequest();
$rules = $request->rules();
$validator = Validator::make($attributes, $rules);#
$passes = $validator->passes();
$this->assertEquals(true, $passes);
}
public function test_form_validation_fails_unused_ticket()
{
$attributes = $this->createAttributes();
// make change to a used ticket
$attributes['ticket']=967;
$request = new \App\Http\Requests\CreateGreenFeeSaleRequest();
$rules = $request->rules();
$validator = Validator::make($attributes, $rules);#
$fails = $validator->fails();
$this->assertEquals(true, $fails);
}
public function test_form_validation_passes_used_ticket_this_reservation()
{
$attributes = $this->createAttributes();
// make change to a used ticket
$attributes['ticket']=967;
$attributes['reservation_id']=1554;
$request = new \App\Http\Requests\CreateGreenFeeSaleRequest();
$rules = $request->rules();
$validator = Validator::make($attributes, $rules);#
var_dump($validator->errors());
$passes = $validator->passes();
$this->assertEquals(true, $passes);
}
}
So:
- How do I pass the
reservation_id to the custom rule from the test
- How should I correctly mock that an authorised user is logged in?
I am struggling with tests despite hours reading and trying to learn - it doesnt stick until I can apply it - I cant apply it till I get it!! (catch 22) So any help appreciated especially on how to construct the tests properly
Thank you