Skip to content

Commit da6b458

Browse files
committed
Handle dates as Carbon objects
1 parent 34cc58c commit da6b458

File tree

6 files changed

+202
-11
lines changed

6 files changed

+202
-11
lines changed

src/Generators/PhpUnitTestGenerator.php

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ protected function buildTestCases(Controller $controller): string
9797
'mock' => [],
9898
];
9999
$request_data = [];
100+
$model_columns = [];
100101
$tested_bits = 0;
101102

102103
$model = $controller->prefix();
@@ -227,11 +228,17 @@ protected function buildTestCases(Controller $controller): string
227228
if ($factory) {
228229
[$faker, $variable_name] = $factory;
229230
} else {
230-
$faker = sprintf('$%s = $this->faker->%s;', $data, FakerRegistry::fakerData($local_column->name()) ?? FakerRegistry::fakerDataType($local_model->column($column)->dataType()));
231+
if ($local_column->isDate()) {
232+
$this->addImport($controller, 'Illuminate\\Support\\Carbon');
233+
$faker = sprintf('$%s = Carbon::parse($this->faker->%s);', $data, FakerRegistry::fakerData($local_column->name()) ?? FakerRegistry::fakerDataType($local_model->column($column)->dataType()));
234+
} else {
235+
$faker = sprintf('$%s = $this->faker->%s;', $data, FakerRegistry::fakerData($local_column->name()) ?? FakerRegistry::fakerDataType($local_model->column($column)->dataType()));
236+
}
231237
}
232238

233239
$setup['data'][] = $faker;
234240
$request_data[$data] = '$' . $variable_name;
241+
$model_columns[$data] = '$' . $variable_name;
235242
} elseif (!is_null($local_model)) {
236243
foreach ($local_model->columns() as $local_column) {
237244
if (in_array($local_column->name(), ['id', 'softdeletes', 'softdeletestz'])) {
@@ -246,12 +253,27 @@ protected function buildTestCases(Controller $controller): string
246253
if ($factory) {
247254
[$faker, $variable_name] = $factory;
248255
} else {
249-
$faker = sprintf('$%s = $this->faker->%s;', $local_column->name(), FakerRegistry::fakerData($local_column->name()) ?? FakerRegistry::fakerDataType($local_column->dataType()));
256+
if ($local_column->isDate()) {
257+
$this->addImport($controller, 'Illuminate\\Support\\Carbon');
258+
$faker = sprintf('$%s = Carbon::parse($this->faker->%s);', $local_column->name(), FakerRegistry::fakerData($local_column->name()) ?? FakerRegistry::fakerDataType($local_column->dataType()));
259+
} else {
260+
$faker = sprintf('$%s = $this->faker->%s;', $local_column->name(), FakerRegistry::fakerData($local_column->name()) ?? FakerRegistry::fakerDataType($local_column->dataType()));
261+
}
250262
$variable_name = $local_column->name();
251263
}
252264

253265
$setup['data'][] = $faker;
254-
$request_data[$local_column->name()] = '$' . $variable_name;
266+
if ($local_column->isDate()) {
267+
if ($local_column->dataType() === 'date') {
268+
$request_data[$local_column->name()] = '$' . $variable_name . '->toDateString()';
269+
} else {
270+
$request_data[$local_column->name()] = '$' . $variable_name . '->toDateTimeString()';
271+
}
272+
} else {
273+
$request_data[$local_column->name()] = '$' . $variable_name;
274+
}
275+
276+
$model_columns[$local_column->name()] = '$' . $variable_name;
255277
}
256278
}
257279
}
@@ -404,11 +426,11 @@ protected function buildTestCases(Controller $controller): string
404426
if ($statement->operation() === 'save') {
405427
$tested_bits |= self::TESTS_SAVE;
406428

407-
if ($request_data) {
429+
if ($model_columns) {
408430
$indent = str_pad(' ', 12);
409431
$plural = Str::plural($variable);
410432
$assertion = sprintf('$%s = %s::query()', $plural, $model);
411-
foreach ($request_data as $key => $datum) {
433+
foreach ($model_columns as $key => $datum) {
412434
$assertion .= PHP_EOL . sprintf('%s->where(\'%s\', %s)', $indent, $key, $datum);
413435
}
414436
$assertion .= PHP_EOL . $indent . '->get();';
@@ -435,13 +457,12 @@ protected function buildTestCases(Controller $controller): string
435457
} elseif ($statement->operation() === 'update') {
436458
$assertions['sanity'][] = sprintf('$%s->refresh();', $variable);
437459

438-
if ($request_data) {
460+
if ($model_columns) {
439461
/** @var \Blueprint\Models\Model $local_model */
440462
$local_model = $this->tree->modelForContext($model);
441-
foreach ($request_data as $key => $datum) {
442-
if (!is_null($local_model) && $local_model->hasColumn($key) && $local_model->column($key)->dataType() === 'date') {
443-
$this->addImport($controller, 'Carbon\\Carbon');
444-
$assertions['generic'][] = sprintf('$this->assertEquals(Carbon::parse(%s), $%s->%s);', $datum, $variable, $key);
463+
foreach ($model_columns as $key => $datum) {
464+
if (!is_null($local_model) && $local_model->hasColumn($key) && $local_model->column($key)->dataType() === 'timestamp') {
465+
$assertions['generic'][] = sprintf('$this->assertEquals(%s->timestamp, $%s->%s);', $datum, $variable, $key);
445466
} else {
446467
$assertions['generic'][] = sprintf('$this->assertEquals(%s, $%s->%s);', $datum, $variable, $key);
447468
}

src/Models/Column.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ public function modifiers(): array
4242
return $this->modifiers;
4343
}
4444

45+
public function isDate()
46+
{
47+
return in_array(strtolower($this->dataType()), [
48+
'date',
49+
'datetime',
50+
'timestamp',
51+
]);
52+
}
53+
4554
public function isForeignKey()
4655
{
4756
return collect($this->modifiers())->filter(fn ($modifier) => (is_array($modifier) && key($modifier) === 'foreign') || $modifier === 'foreign')->flatten()->first();

src/Models/Model.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ public function hasColumn(string $name): bool
176176
return isset($this->columns[$name]);
177177
}
178178

179-
public function column(string $name)
179+
public function column(string $name): Column
180180
{
181181
return $this->columns[$name];
182182
}

tests/Feature/Generators/PhpUnitTestGeneratorTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ public static function controllerTreeDataProvider(): array
224224
['drafts/crud-show-only.yaml', 'tests/Feature/Http/Controllers/PostControllerTest.php', 'tests/phpunit/crud-show-only.php'],
225225
['drafts/model-reference-validate.yaml', 'tests/Feature/Http/Controllers/CertificateControllerTest.php', 'tests/phpunit/api-shorthand-validation.php'],
226226
['drafts/controllers-only-no-context.yaml', 'tests/Feature/Http/Controllers/ReportControllerTest.php', 'tests/phpunit/controllers-only-no-context.php'],
227+
['drafts/date-formats.yaml', 'tests/Feature/Http/Controllers/DateControllerTest.php', 'tests/phpunit/date-formats.php'],
227228
['drafts/call-to-a-member-function-columns-on-null.yaml', [
228229
'tests/Feature/Http/Controllers/SubscriptionControllerTest.php',
229230
'tests/Feature/Http/Controllers/TelegramControllerTest.php',
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
models:
2+
Date:
3+
born_at: date
4+
expires_at: datetime
5+
published_at: timestamp
6+
7+
controllers:
8+
Date:
9+
resource: web
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
<?php
2+
3+
namespace Tests\Feature\Http\Controllers;
4+
5+
use App\Models\Date;
6+
use Illuminate\Foundation\Testing\RefreshDatabase;
7+
use Illuminate\Foundation\Testing\WithFaker;
8+
use Illuminate\Support\Carbon;
9+
use JMac\Testing\Traits\AdditionalAssertions;
10+
use PHPUnit\Framework\Attributes\Test;
11+
use Tests\TestCase;
12+
13+
/**
14+
* @see \App\Http\Controllers\DateController
15+
*/
16+
final class DateControllerTest extends TestCase
17+
{
18+
use AdditionalAssertions, RefreshDatabase, WithFaker;
19+
20+
#[Test]
21+
public function index_displays_view(): void
22+
{
23+
$dates = Date::factory()->count(3)->create();
24+
25+
$response = $this->get(route('date.index'));
26+
27+
$response->assertOk();
28+
$response->assertViewIs('date.index');
29+
$response->assertViewHas('dates');
30+
}
31+
32+
33+
#[Test]
34+
public function create_displays_view(): void
35+
{
36+
$response = $this->get(route('date.create'));
37+
38+
$response->assertOk();
39+
$response->assertViewIs('date.create');
40+
}
41+
42+
43+
#[Test]
44+
public function store_uses_form_request_validation(): void
45+
{
46+
$this->assertActionUsesFormRequest(
47+
\App\Http\Controllers\DateController::class,
48+
'store',
49+
\App\Http\Requests\DateStoreRequest::class
50+
);
51+
}
52+
53+
#[Test]
54+
public function store_saves_and_redirects(): void
55+
{
56+
$born_at = Carbon::parse($this->faker->date());
57+
$expires_at = Carbon::parse($this->faker->dateTime());
58+
$published_at = Carbon::parse($this->faker->dateTime());
59+
60+
$response = $this->post(route('date.store'), [
61+
'born_at' => $born_at->toDateString(),
62+
'expires_at' => $expires_at->toDateTimeString(),
63+
'published_at' => $published_at->toDateTimeString(),
64+
]);
65+
66+
$dates = Date::query()
67+
->where('born_at', $born_at)
68+
->where('expires_at', $expires_at)
69+
->where('published_at', $published_at)
70+
->get();
71+
$this->assertCount(1, $dates);
72+
$date = $dates->first();
73+
74+
$response->assertRedirect(route('date.index'));
75+
$response->assertSessionHas('date.id', $date->id);
76+
}
77+
78+
79+
#[Test]
80+
public function show_displays_view(): void
81+
{
82+
$date = Date::factory()->create();
83+
84+
$response = $this->get(route('date.show', $date));
85+
86+
$response->assertOk();
87+
$response->assertViewIs('date.show');
88+
$response->assertViewHas('date');
89+
}
90+
91+
92+
#[Test]
93+
public function edit_displays_view(): void
94+
{
95+
$date = Date::factory()->create();
96+
97+
$response = $this->get(route('date.edit', $date));
98+
99+
$response->assertOk();
100+
$response->assertViewIs('date.edit');
101+
$response->assertViewHas('date');
102+
}
103+
104+
105+
#[Test]
106+
public function update_uses_form_request_validation(): void
107+
{
108+
$this->assertActionUsesFormRequest(
109+
\App\Http\Controllers\DateController::class,
110+
'update',
111+
\App\Http\Requests\DateUpdateRequest::class
112+
);
113+
}
114+
115+
#[Test]
116+
public function update_redirects(): void
117+
{
118+
$date = Date::factory()->create();
119+
$born_at = Carbon::parse($this->faker->date());
120+
$expires_at = Carbon::parse($this->faker->dateTime());
121+
$published_at = Carbon::parse($this->faker->dateTime());
122+
123+
$response = $this->put(route('date.update', $date), [
124+
'born_at' => $born_at->toDateString(),
125+
'expires_at' => $expires_at->toDateTimeString(),
126+
'published_at' => $published_at->toDateTimeString(),
127+
]);
128+
129+
$date->refresh();
130+
131+
$response->assertRedirect(route('date.index'));
132+
$response->assertSessionHas('date.id', $date->id);
133+
134+
$this->assertEquals($born_at, $date->born_at);
135+
$this->assertEquals($expires_at, $date->expires_at);
136+
$this->assertEquals($published_at->timestamp, $date->published_at);
137+
}
138+
139+
140+
#[Test]
141+
public function destroy_deletes_and_redirects(): void
142+
{
143+
$date = Date::factory()->create();
144+
145+
$response = $this->delete(route('date.destroy', $date));
146+
147+
$response->assertRedirect(route('date.index'));
148+
149+
$this->assertModelMissing($date);
150+
}
151+
}

0 commit comments

Comments
 (0)