Testing Laravel Form Request with custom rules

Posted 1 year ago by longestdrive

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:

  1. How do I pass the reservation_id to the custom rule from the test
  2. 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

Please sign in or create an account to participate in this conversation.

Reply to

Use Markdown with GitHub-flavored code blocks.