Skip to content

Commit 0d82e12

Browse files
Updates for more README example (#273)
1 parent b91dafd commit 0d82e12

File tree

16 files changed

+122
-54
lines changed

16 files changed

+122
-54
lines changed

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ models:
3939
title: string:400
4040
content: longtext
4141
published_at: nullable timestamp
42+
author_id: id:user
4243

4344
controllers:
4445
Post:
@@ -47,9 +48,9 @@ controllers:
4748
render: post.index with:posts
4849

4950
store:
50-
validate: title, content
51+
validate: title, content, author_id
5152
save: post
52-
send: ReviewNotification to:post.author with:post
53+
send: ReviewPost to:post.author.email with:post
5354
dispatch: SyncMedia with:post
5455
fire: NewPost with:post
5556
flash: post.title
@@ -64,10 +65,13 @@ From these simple 20 lines of YAML, Blueprint will generate all of the following
6465
- A _controller_ class for `PostController` with `index` and `store` actions complete with code generated for each [statement](https://blueprint.laravelshift.com/docs/controller-statements/).
6566
- _Routes_ for the `PostController` actions.
6667
- A [_form request_](https://laravel.com/docs/validation#form-request-validation) of `StorePostRequest` validating `title` and `content` based on the `Post` model definition.
67-
- A _mailable_ class for `ReviewNotification` complete with a `post` property set through the _constructor_.
68+
- A _mailable_ class for `ReviewPost` complete with a `post` property set through the _constructor_.
6869
- A _job_ class for `SyncMedia` complete with a `post` property set through the _constructor_.
6970
- An _event_ class for `NewPost` complete with a `post` property set through the _constructor_.
7071
- A _Blade template_ of `post/index.blade.php` rendered by `PostController@index`.
7172

73+
_**Note:** This example assumes features within a default Laravel application such as the `User` model and `app.blade.php
74+
layout. Otherwise, the generated test may have failures._
75+
7276
## Documentation
7377
Browse the [Blueprint Docs](https://blueprint.laravelshift.com/) for full details on [defining models](https://blueprint.laravelshift.com/docs/defining-models/), [defining controllers](https://blueprint.laravelshift.com/docs/defining-controllers/), [advanced configuration](https://blueprint.laravelshift.com/docs/advanced-configuration/), and [extending Blueprint](https://blueprint.laravelshift.com/docs/extending-blueprint/).

src/Generators/TestGenerator.php

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ protected function buildTestCases(Controller $controller)
106106
$context = Str::singular($controller->prefix());
107107
$variable = Str::camel($context);
108108

109+
$modelNamespace = config('blueprint.models_namespace')
110+
? config('blueprint.namespace') . '\\' . config('blueprint.models_namespace')
111+
: config('blueprint.namespace');
112+
109113
if (in_array($name, ['edit', 'update', 'show', 'destroy'])) {
110114
$setup['data'][] = sprintf('$%s = factory(%s::class)->create();', $variable, $model);
111115
}
@@ -211,16 +215,33 @@ protected function buildTestCases(Controller $controller)
211215
$qualifier = $context;
212216
}
213217

214-
/** @var \Blueprint\Models\Model $model */
218+
$variable_name = $data;
219+
220+
/** @var \Blueprint\Models\Model $local_model */
215221
$local_model = $this->modelForContext($qualifier);
222+
216223
if (!is_null($local_model) && $local_model->hasColumn($column)) {
217-
$faker = FactoryGenerator::fakerData($local_model->column($column)->name()) ?? FactoryGenerator::fakerDataType($local_model->column($column)->dataType());
224+
$local_column = $local_model->column($column);
225+
if (($local_column->dataType() === 'id' || $local_column->dataType() === 'uuid') && ($local_column->attributes() && Str::endsWith($local_column->name(), '_id'))) {
226+
$variable_name = Str::beforeLast($local_column->name(), '_id');
227+
$reference = $variable_name;
228+
229+
if ($local_column->attributes()) {
230+
$reference = $local_column->attributes()[0];
231+
$variable_name .= '->id';
232+
}
233+
$faker = sprintf('$%s = factory(%s::class)->create();', Str::beforeLast($local_column->name(), '_id'), Str::studly($reference));
234+
235+
$this->addImport($controller, $modelNamespace . '\\' . Str::studly($reference));
236+
} else {
237+
$faker = sprintf('$%s = $this->faker->%s;', $data, FactoryGenerator::fakerData($local_column->name()) ?? FactoryGenerator::fakerDataType($local_model->column($column)->dataType()));
238+
}
218239
} else {
219-
$faker = 'word';
240+
$faker = sprintf('$%s = $this->faker->word;', $data);
220241
}
221242

222-
$setup['data'][] = sprintf('$%s = $this->faker->%s;', $data, $faker);
223-
$request_data[$data] = '$' . $data;
243+
$setup['data'][] = $faker;
244+
$request_data[$data] = '$' . $variable_name;
224245
}
225246
}
226247
} elseif ($statement instanceof DispatchStatement) {
@@ -357,10 +378,6 @@ protected function buildTestCases(Controller $controller)
357378
} elseif ($statement instanceof EloquentStatement) {
358379
$this->addRefreshDatabaseTrait($controller);
359380

360-
$modelNamespace = config('blueprint.models_namespace')
361-
? config('blueprint.namespace') . '\\' . config('blueprint.models_namespace')
362-
: config('blueprint.namespace');
363-
364381
$model = $this->determineModel($controller->prefix(), $statement->reference());
365382
$this->addImport($controller, $modelNamespace . '\\' . $model);
366383

@@ -394,10 +411,6 @@ protected function buildTestCases(Controller $controller)
394411

395412
$setup['data'][] = sprintf('$%s = factory(%s::class, 3)->create();', Str::plural($variable), $model);
396413

397-
$modelNamespace = config('blueprint.models_namespace')
398-
? config('blueprint.namespace') . '\\' . config('blueprint.models_namespace')
399-
: config('blueprint.namespace');
400-
401414
$this->addImport($controller, $modelNamespace . '\\' . $this->determineModel($controller->prefix(), $statement->model()));
402415
}
403416
}

src/Translators/Rules.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ public static function fromColumn(string $context, Column $column)
2020
array_push($rules, self::overrideStringRuleForSpecialNames($column->name()));
2121
}
2222

23-
if ($column->dataType() === 'id' && Str::endsWith($column->name(), '_id')) {
24-
$rules = array_merge($rules, ['integer', 'exists:' . Str::plural(Str::beforeLast($column->name(), '_id')) . ',id']);
23+
if ($column->dataType() === 'id' && ($column->attributes() || Str::endsWith($column->name(), '_id'))) {
24+
$reference = $column->attributes()[0] ?? Str::beforeLast($column->name(), '_id');
25+
$rules = array_merge($rules, ['integer', 'exists:' . Str::plural($reference) . ',id']);
2526
}
2627

2728
if (in_array($column->dataType(), [

tests/Feature/BlueprintTest.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,18 +208,19 @@ public function it_parses_the_readme_example()
208208
'title' => 'string:400',
209209
'content' => 'longtext',
210210
'published_at' => 'nullable timestamp',
211+
'author_id' => 'id:user',
211212
],
212213
],
213214
'controllers' => [
214215
'Post' => [
215216
'index' => [
216-
'query' => 'all:posts',
217+
'query' => 'all',
217218
'render' => 'post.index with:posts',
218219
],
219220
'store' => [
220-
'validate' => 'title, content',
221+
'validate' => 'title, content, author_id',
221222
'save' => 'post',
222-
'send' => 'ReviewMail to:post.author with:post',
223+
'send' => 'ReviewPost to:post.author.email with:post',
223224
'dispatch' => 'SyncMedia with:post',
224225
'fire' => 'NewPost with:post',
225226
'flash' => 'post.title',
@@ -250,18 +251,19 @@ public function it_parses_the_readme_example_with_different_platform_eols()
250251
'title' => 'string:400',
251252
'content' => 'longtext',
252253
'published_at' => 'nullable timestamp',
254+
'author_id' => 'id:user',
253255
],
254256
],
255257
'controllers' => [
256258
'Post' => [
257259
'index' => [
258-
'query' => 'all:posts',
260+
'query' => 'all',
259261
'render' => 'post.index with:posts',
260262
],
261263
'store' => [
262-
'validate' => 'title, content',
264+
'validate' => 'title, content, author_id',
263265
'save' => 'post',
264-
'send' => 'ReviewMail to:post.author with:post',
266+
'send' => 'ReviewPost to:post.author.email with:post',
265267
'dispatch' => 'SyncMedia with:post',
266268
'fire' => 'NewPost with:post',
267269
'flash' => 'post.title',

tests/Feature/Generator/Statements/MailGeneratorTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,16 @@ public function it_respects_configuration()
137137
->with('src/path/Mail')
138138
->andReturnFalse();
139139
$this->files->expects('exists')
140-
->with('src/path/Mail/ReviewMail.php')
140+
->with('src/path/Mail/ReviewPost.php')
141141
->andReturnFalse();
142142
$this->files->expects('makeDirectory')
143143
->with('src/path/Mail', 0755, true);
144144
$this->files->expects('put')
145-
->with('src/path/Mail/ReviewMail.php', $this->fixture('mailables/mail-configured.php'));
145+
->with('src/path/Mail/ReviewPost.php', $this->fixture('mailables/mail-configured.php'));
146146

147147
$tokens = $this->blueprint->parse($this->fixture('drafts/readme-example.yaml'));
148148
$tree = $this->blueprint->analyze($tokens);
149149

150-
$this->assertEquals(['created' => ['src/path/Mail/ReviewMail.php']], $this->subject->output($tree));
150+
$this->assertEquals(['created' => ['src/path/Mail/ReviewPost.php']], $this->subject->output($tree));
151151
}
152152
}

tests/Feature/Lexers/StatementLexerTest.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,15 @@ public function it_returns_a_dispatch_statement_with_data()
155155
public function it_returns_a_send_statement()
156156
{
157157
$tokens = [
158-
'send' => 'ReviewMail'
158+
'send' => 'ReviewPost'
159159
];
160160

161161
$actual = $this->subject->analyze($tokens);
162162

163163
$this->assertCount(1, $actual);
164164
$this->assertInstanceOf(SendStatement::class, $actual[0]);
165165

166-
$this->assertEquals('ReviewMail', $actual[0]->mail());
166+
$this->assertEquals('ReviewPost', $actual[0]->mail());
167167
$this->assertNull($actual[0]->to());
168168
$this->assertSame([], $actual[0]->data());
169169
}
@@ -174,15 +174,15 @@ public function it_returns_a_send_statement()
174174
public function it_returns_a_send_statement_to_only()
175175
{
176176
$tokens = [
177-
'send' => 'ReviewMail to:post.author'
177+
'send' => 'ReviewPost to:post.author'
178178
];
179179

180180
$actual = $this->subject->analyze($tokens);
181181

182182
$this->assertCount(1, $actual);
183183
$this->assertInstanceOf(SendStatement::class, $actual[0]);
184184

185-
$this->assertEquals('ReviewMail', $actual[0]->mail());
185+
$this->assertEquals('ReviewPost', $actual[0]->mail());
186186
$this->assertEquals('post.author', $actual[0]->to());
187187
$this->assertSame([], $actual[0]->data());
188188
}
@@ -193,15 +193,15 @@ public function it_returns_a_send_statement_to_only()
193193
public function it_returns_a_send_statement_with_only()
194194
{
195195
$tokens = [
196-
'send' => 'ReviewMail with:foo, bar, baz'
196+
'send' => 'ReviewPost with:foo, bar, baz'
197197
];
198198

199199
$actual = $this->subject->analyze($tokens);
200200

201201
$this->assertCount(1, $actual);
202202
$this->assertInstanceOf(SendStatement::class, $actual[0]);
203203

204-
$this->assertEquals('ReviewMail', $actual[0]->mail());
204+
$this->assertEquals('ReviewPost', $actual[0]->mail());
205205
$this->assertNull($actual[0]->to());
206206
$this->assertEquals(['foo', 'bar', 'baz'], $actual[0]->data());
207207
}
@@ -212,15 +212,15 @@ public function it_returns_a_send_statement_with_only()
212212
public function it_returns_a_send_statement_to_and_with()
213213
{
214214
$tokens = [
215-
'send' => 'ReviewMail to:post.author with:foo, bar, baz'
215+
'send' => 'ReviewPost to:post.author with:foo, bar, baz'
216216
];
217217

218218
$actual = $this->subject->analyze($tokens);
219219

220220
$this->assertCount(1, $actual);
221221
$this->assertInstanceOf(SendStatement::class, $actual[0]);
222222

223-
$this->assertEquals('ReviewMail', $actual[0]->mail());
223+
$this->assertEquals('ReviewPost', $actual[0]->mail());
224224
$this->assertEquals('post.author', $actual[0]->to());
225225
$this->assertEquals(['foo', 'bar', 'baz'], $actual[0]->data());
226226
}

tests/Feature/Translators/RulesTest.php

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,36 @@ public function forColumn_returns_integer_rule_for_integer_types($data_type)
9696
$this->assertContains('integer', Rules::fromColumn('context', $column));
9797
}
9898

99+
/**
100+
* @test
101+
*/
102+
public function forColumn_return_exists_rule_for_id_column()
103+
{
104+
$column = new Column('user_id', 'id');
105+
106+
$this->assertContains('exists:users,id', Rules::fromColumn('context', $column));
107+
}
108+
109+
/**
110+
* @test
111+
*/
112+
public function forColumn_return_exists_rule_id_column_with_attribute()
113+
{
114+
$column = new Column('author_id', 'id', [], ['user']);
115+
116+
$this->assertContains('exists:users,id', Rules::fromColumn('context', $column));
117+
}
118+
119+
/**
120+
* @test
121+
*/
122+
public function forColumn_return_exists_rule_for_the_unique_modifier()
123+
{
124+
$column = new Column('column', 'string', ['unique']);
125+
126+
$this->assertContains('unique:connection.table,column', Rules::fromColumn('connection.table', $column));
127+
}
128+
99129
/**
100130
* @test
101131
* @dataProvider relationshipColumnProvider
@@ -148,16 +178,6 @@ public function forColumn_returns_date_rule_for_date_types($data_type)
148178
$this->assertContains('date', Rules::fromColumn('context', $column));
149179
}
150180

151-
/**
152-
* @test
153-
*/
154-
public function forColumn_return_exists_rule_for_the_unique_modifier()
155-
{
156-
$column = new Column('column', 'string', ['unique']);
157-
158-
$this->assertContains('unique:connection.table,column', Rules::fromColumn('connection.table', $column));
159-
}
160-
161181
/**
162182
* @test
163183
*/

tests/fixtures/controllers/readme-example.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use App\Events\NewPost;
66
use App\Http\Requests\PostStoreRequest;
77
use App\Jobs\SyncMedia;
8-
use App\Mail\ReviewMail;
8+
use App\Mail\ReviewPost;
99
use App\Post;
1010
use Illuminate\Http\Request;
1111
use Illuminate\Support\Facades\Mail;
@@ -31,7 +31,7 @@ public function store(PostStoreRequest $request)
3131
{
3232
$post = Post::create($request->all());
3333

34-
Mail::to($post->author)->send(new ReviewMail($post));
34+
Mail::to($post->author->email)->send(new ReviewPost($post));
3535

3636
SyncMedia::dispatch($post);
3737

tests/fixtures/drafts/readme-example.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@ models:
33
title: string:400
44
content: longtext
55
published_at: nullable timestamp
6+
author_id: id:user
67

78
controllers:
89
Post:
910
index:
10-
query: all:posts
11+
query: all
1112
render: post.index with:posts
1213

1314
store:
14-
validate: title, content
15+
validate: title, content, author_id
1516
save: post
16-
send: ReviewMail to:post.author with:post
17+
send: ReviewPost to:post.author.email with:post
1718
dispatch: SyncMedia with:post
1819
fire: NewPost with:post
1920
flash: post.title

tests/fixtures/factories/fake-nullables.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
return [
1010
'title' => $faker->sentence(4),
1111
'content' => $faker->paragraphs(3, true),
12+
'author_id' => factory(\App\User::class),
1213
];
1314
});

0 commit comments

Comments
 (0)