0

I am trying to write a test that checks that a date is formatted correctly. Looking at the docs it seems pretty straight-forward.

Here is my test. I am submitting an invalid date format to my controller:

MyTest.php

 /** @test */
public function a_date_must_be_formatted_correctly()
{
    $foo = factory(Foo::class)->raw([
        'date' => date('d/m/Y'),
    ]);

    $response = $this->postJson('api/v1/foo', $foo)
        ->assertStatus(422)
        ->assertJsonValidationErrors('date');
}

Here is my controller method:

public function store(Request $request)
{
    $attributes = $request->validate([
        'date' => 'required|date_format:Y-m-d',
    ]);
    ...
}

I get a passing test each time.

I have also tried wrapping the format in quotes: 'date' => 'required|date_format:"Y-m-d"',

I'm expecting to get a 422 back saying my date is invalid. What am I doing wrong?

Damon
  • 4,151
  • 13
  • 52
  • 108
  • What's `Foo::class`? – apokryfos Feb 10 '20 at 16:23
  • It's my example model (In my case it's a `Blackout`). It has a fillable attribute of `date` that I'm trying to make sure the correct format is passed in. – Damon Feb 10 '20 at 16:33
  • What does `json_serialize($foo)` look like? Usually you'd send an array of data to test inputs and not the actual model itself – apokryfos Feb 10 '20 at 16:36
  • That's likely the issue. I'm learning about TDD so my apologies. I'll try and update my answer if needed. Thank you for the suggestion! – Damon Feb 10 '20 at 16:40

1 Answers1

0

Well, I ended up writing a custom rule. I don't think this is the correct solution though given that Laravel has the handy built-in stuff. I feel like I should be leveraging that instead. In my case I am working with Blackout date(s).

Hers is what I ended up with. If there is a way to make the built-in methods work, please let me know so I can update the answer.

MyTest.php

/** @test */
public function a_blackout_date_must_be_formatted_correctly()
{
    $blackout = factory(Blackout::class)->raw([
        'date' => date('d/m/Y'),
    ]);

    $response = $this->postJson('api/v1/blackouts', $blackout)
        ->assertStatus(422)
        ->assertJsonValidationErrors('date');
}

MyController.php

public function store(Request $request)
{
    $attributes = $request->validate([
        'date' => ['required', new DateFormatRule],
        ...
    ]);

    $blackout = new Blackout($attributes);

    ...

}

DateFormatRule.php

public function passes($attribute, $value)
{
    // The format we're looking for.
    $format = 'Y-m-d';

    // Create a new DateTime object.
    $date = DateTime::createFromFormat($format, $value);

    // Verify that the date provided is formatted correctly.
    return $date && $date->format($format) === $value;
}

/**
 * Get the validation error message.
 *
 * @return string
 */
public function message()
{
    return 'Invalid date format.';
}

In my test I am getting a 422 response as expected. I can verify things are working by changing the name of the expected error from date to date123 and I'll get an error -- saying It was expecting date not date123.

Hope this helps someone!

Damon
  • 4,151
  • 13
  • 52
  • 108