Skip to content

Commit

Permalink
Handle dates as Carbon objects
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonmccreary committed Feb 29, 2024
1 parent 34cc58c commit da6b458
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 11 deletions.
41 changes: 31 additions & 10 deletions src/Generators/PhpUnitTestGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ protected function buildTestCases(Controller $controller): string
'mock' => [],
];
$request_data = [];
$model_columns = [];
$tested_bits = 0;

$model = $controller->prefix();
Expand Down Expand Up @@ -227,11 +228,17 @@ protected function buildTestCases(Controller $controller): string
if ($factory) {
[$faker, $variable_name] = $factory;
} else {
$faker = sprintf('$%s = $this->faker->%s;', $data, FakerRegistry::fakerData($local_column->name()) ?? FakerRegistry::fakerDataType($local_model->column($column)->dataType()));
if ($local_column->isDate()) {
$this->addImport($controller, 'Illuminate\\Support\\Carbon');
$faker = sprintf('$%s = Carbon::parse($this->faker->%s);', $data, FakerRegistry::fakerData($local_column->name()) ?? FakerRegistry::fakerDataType($local_model->column($column)->dataType()));
} else {
$faker = sprintf('$%s = $this->faker->%s;', $data, FakerRegistry::fakerData($local_column->name()) ?? FakerRegistry::fakerDataType($local_model->column($column)->dataType()));
}
}

$setup['data'][] = $faker;
$request_data[$data] = '$' . $variable_name;
$model_columns[$data] = '$' . $variable_name;
} elseif (!is_null($local_model)) {
foreach ($local_model->columns() as $local_column) {
if (in_array($local_column->name(), ['id', 'softdeletes', 'softdeletestz'])) {
Expand All @@ -246,12 +253,27 @@ protected function buildTestCases(Controller $controller): string
if ($factory) {
[$faker, $variable_name] = $factory;
} else {
$faker = sprintf('$%s = $this->faker->%s;', $local_column->name(), FakerRegistry::fakerData($local_column->name()) ?? FakerRegistry::fakerDataType($local_column->dataType()));
if ($local_column->isDate()) {
$this->addImport($controller, 'Illuminate\\Support\\Carbon');
$faker = sprintf('$%s = Carbon::parse($this->faker->%s);', $local_column->name(), FakerRegistry::fakerData($local_column->name()) ?? FakerRegistry::fakerDataType($local_column->dataType()));
} else {
$faker = sprintf('$%s = $this->faker->%s;', $local_column->name(), FakerRegistry::fakerData($local_column->name()) ?? FakerRegistry::fakerDataType($local_column->dataType()));
}
$variable_name = $local_column->name();
}

$setup['data'][] = $faker;
$request_data[$local_column->name()] = '$' . $variable_name;
if ($local_column->isDate()) {
if ($local_column->dataType() === 'date') {
$request_data[$local_column->name()] = '$' . $variable_name . '->toDateString()';
} else {
$request_data[$local_column->name()] = '$' . $variable_name . '->toDateTimeString()';
}
} else {
$request_data[$local_column->name()] = '$' . $variable_name;
}

$model_columns[$local_column->name()] = '$' . $variable_name;
}
}
}
Expand Down Expand Up @@ -404,11 +426,11 @@ protected function buildTestCases(Controller $controller): string
if ($statement->operation() === 'save') {
$tested_bits |= self::TESTS_SAVE;

if ($request_data) {
if ($model_columns) {
$indent = str_pad(' ', 12);
$plural = Str::plural($variable);
$assertion = sprintf('$%s = %s::query()', $plural, $model);
foreach ($request_data as $key => $datum) {
foreach ($model_columns as $key => $datum) {
$assertion .= PHP_EOL . sprintf('%s->where(\'%s\', %s)', $indent, $key, $datum);
}
$assertion .= PHP_EOL . $indent . '->get();';
Expand All @@ -435,13 +457,12 @@ protected function buildTestCases(Controller $controller): string
} elseif ($statement->operation() === 'update') {
$assertions['sanity'][] = sprintf('$%s->refresh();', $variable);

if ($request_data) {
if ($model_columns) {
/** @var \Blueprint\Models\Model $local_model */
$local_model = $this->tree->modelForContext($model);
foreach ($request_data as $key => $datum) {
if (!is_null($local_model) && $local_model->hasColumn($key) && $local_model->column($key)->dataType() === 'date') {
$this->addImport($controller, 'Carbon\\Carbon');
$assertions['generic'][] = sprintf('$this->assertEquals(Carbon::parse(%s), $%s->%s);', $datum, $variable, $key);
foreach ($model_columns as $key => $datum) {
if (!is_null($local_model) && $local_model->hasColumn($key) && $local_model->column($key)->dataType() === 'timestamp') {
$assertions['generic'][] = sprintf('$this->assertEquals(%s->timestamp, $%s->%s);', $datum, $variable, $key);
} else {
$assertions['generic'][] = sprintf('$this->assertEquals(%s, $%s->%s);', $datum, $variable, $key);
}
Expand Down
9 changes: 9 additions & 0 deletions src/Models/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ public function modifiers(): array
return $this->modifiers;
}

public function isDate()
{
return in_array(strtolower($this->dataType()), [
'date',
'datetime',
'timestamp',
]);
}

public function isForeignKey()
{
return collect($this->modifiers())->filter(fn ($modifier) => (is_array($modifier) && key($modifier) === 'foreign') || $modifier === 'foreign')->flatten()->first();
Expand Down
2 changes: 1 addition & 1 deletion src/Models/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ public function hasColumn(string $name): bool
return isset($this->columns[$name]);
}

public function column(string $name)
public function column(string $name): Column
{
return $this->columns[$name];
}
Expand Down
1 change: 1 addition & 0 deletions tests/Feature/Generators/PhpUnitTestGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ public static function controllerTreeDataProvider(): array
['drafts/crud-show-only.yaml', 'tests/Feature/Http/Controllers/PostControllerTest.php', 'tests/phpunit/crud-show-only.php'],
['drafts/model-reference-validate.yaml', 'tests/Feature/Http/Controllers/CertificateControllerTest.php', 'tests/phpunit/api-shorthand-validation.php'],
['drafts/controllers-only-no-context.yaml', 'tests/Feature/Http/Controllers/ReportControllerTest.php', 'tests/phpunit/controllers-only-no-context.php'],
['drafts/date-formats.yaml', 'tests/Feature/Http/Controllers/DateControllerTest.php', 'tests/phpunit/date-formats.php'],
['drafts/call-to-a-member-function-columns-on-null.yaml', [
'tests/Feature/Http/Controllers/SubscriptionControllerTest.php',
'tests/Feature/Http/Controllers/TelegramControllerTest.php',
Expand Down
9 changes: 9 additions & 0 deletions tests/fixtures/drafts/date-formats.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
models:
Date:
born_at: date
expires_at: datetime
published_at: timestamp

controllers:
Date:
resource: web
151 changes: 151 additions & 0 deletions tests/fixtures/tests/phpunit/date-formats.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

namespace Tests\Feature\Http\Controllers;

use App\Models\Date;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Carbon;
use JMac\Testing\Traits\AdditionalAssertions;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;

/**
* @see \App\Http\Controllers\DateController
*/
final class DateControllerTest extends TestCase
{
use AdditionalAssertions, RefreshDatabase, WithFaker;

#[Test]
public function index_displays_view(): void
{
$dates = Date::factory()->count(3)->create();

$response = $this->get(route('date.index'));

$response->assertOk();
$response->assertViewIs('date.index');
$response->assertViewHas('dates');
}


#[Test]
public function create_displays_view(): void
{
$response = $this->get(route('date.create'));

$response->assertOk();
$response->assertViewIs('date.create');
}


#[Test]
public function store_uses_form_request_validation(): void
{
$this->assertActionUsesFormRequest(
\App\Http\Controllers\DateController::class,
'store',
\App\Http\Requests\DateStoreRequest::class
);
}

#[Test]
public function store_saves_and_redirects(): void
{
$born_at = Carbon::parse($this->faker->date());
$expires_at = Carbon::parse($this->faker->dateTime());
$published_at = Carbon::parse($this->faker->dateTime());

$response = $this->post(route('date.store'), [
'born_at' => $born_at->toDateString(),
'expires_at' => $expires_at->toDateTimeString(),
'published_at' => $published_at->toDateTimeString(),
]);

$dates = Date::query()
->where('born_at', $born_at)
->where('expires_at', $expires_at)
->where('published_at', $published_at)
->get();
$this->assertCount(1, $dates);
$date = $dates->first();

$response->assertRedirect(route('date.index'));
$response->assertSessionHas('date.id', $date->id);
}


#[Test]
public function show_displays_view(): void
{
$date = Date::factory()->create();

$response = $this->get(route('date.show', $date));

$response->assertOk();
$response->assertViewIs('date.show');
$response->assertViewHas('date');
}


#[Test]
public function edit_displays_view(): void
{
$date = Date::factory()->create();

$response = $this->get(route('date.edit', $date));

$response->assertOk();
$response->assertViewIs('date.edit');
$response->assertViewHas('date');
}


#[Test]
public function update_uses_form_request_validation(): void
{
$this->assertActionUsesFormRequest(
\App\Http\Controllers\DateController::class,
'update',
\App\Http\Requests\DateUpdateRequest::class
);
}

#[Test]
public function update_redirects(): void
{
$date = Date::factory()->create();
$born_at = Carbon::parse($this->faker->date());
$expires_at = Carbon::parse($this->faker->dateTime());
$published_at = Carbon::parse($this->faker->dateTime());

$response = $this->put(route('date.update', $date), [
'born_at' => $born_at->toDateString(),
'expires_at' => $expires_at->toDateTimeString(),
'published_at' => $published_at->toDateTimeString(),
]);

$date->refresh();

$response->assertRedirect(route('date.index'));
$response->assertSessionHas('date.id', $date->id);

$this->assertEquals($born_at, $date->born_at);
$this->assertEquals($expires_at, $date->expires_at);
$this->assertEquals($published_at->timestamp, $date->published_at);
}


#[Test]
public function destroy_deletes_and_redirects(): void
{
$date = Date::factory()->create();

$response = $this->delete(route('date.destroy', $date));

$response->assertRedirect(route('date.index'));

$this->assertModelMissing($date);
}
}

0 comments on commit da6b458

Please sign in to comment.