From 744abfdc9896e7811170eae2d34d44fd4306fa34 Mon Sep 17 00:00:00 2001 From: Gianluca Bine Date: Mon, 4 May 2020 18:56:07 -0300 Subject: [PATCH] Fix controller/resource generation with PascalCase definition --- src/Generators/TestGenerator.php | 4 +- src/Lexers/ControllerLexer.php | 2 +- src/Models/Statements/EloquentStatement.php | 8 +- src/Models/Statements/QueryStatement.php | 8 +- .../Generator/ControllerGeneratorTest.php | 33 ++++++ .../Feature/Generator/ModelGeneratorTest.php | 42 +++++++ tests/Feature/Generator/TestGeneratorTest.php | 33 ++++++ .../controllers/certificate-controller.php | 67 +++++++++++ .../certificate-type-controller.php | 67 +++++++++++ tests/fixtures/definitions/pascal-case.bp | 18 +++ .../certificate-pascal-case-example.php | 38 ++++++ .../certificate-type-pascal-case-example.php | 32 +++++ .../tests/certificate-pascal-case-example.php | 110 ++++++++++++++++++ .../certificate-type-pascal-case-example.php | 110 ++++++++++++++++++ 14 files changed, 561 insertions(+), 11 deletions(-) create mode 100644 tests/fixtures/controllers/certificate-controller.php create mode 100644 tests/fixtures/controllers/certificate-type-controller.php create mode 100644 tests/fixtures/definitions/pascal-case.bp create mode 100644 tests/fixtures/models/certificate-pascal-case-example.php create mode 100644 tests/fixtures/models/certificate-type-pascal-case-example.php create mode 100644 tests/fixtures/tests/certificate-pascal-case-example.php create mode 100644 tests/fixtures/tests/certificate-type-pascal-case-example.php diff --git a/src/Generators/TestGenerator.php b/src/Generators/TestGenerator.php index a1a6e03f..37d04afd 100644 --- a/src/Generators/TestGenerator.php +++ b/src/Generators/TestGenerator.php @@ -333,7 +333,7 @@ protected function buildTestCases(Controller $controller) $assertions['sanity'][] = '$this->assertCount(1, $' . $plural . ');'; $assertions['sanity'][] = sprintf('$%s = $%s->first();', $variable, $plural); } else { - $assertions['generic'][] = '$this->assertDatabaseHas(' . Str::lower(Str::plural($model)) . ', [ /* ... */ ]);'; + $assertions['generic'][] = '$this->assertDatabaseHas(' . Str::camel(Str::plural($model)) . ', [ /* ... */ ]);'; } } elseif ($statement->operation() === 'find') { $setup['data'][] = sprintf('$%s = factory(%s::class)->create();', $variable, $model); @@ -351,7 +351,7 @@ protected function buildTestCases(Controller $controller) } } - $call = sprintf('$response = $this->%s(route(\'%s.%s\'', $this->httpMethodForAction($name), Str::lower($context), $name); + $call = sprintf('$response = $this->%s(route(\'%s.%s\'', $this->httpMethodForAction($name), Str::kebab($context), $name); if (in_array($name, ['edit', 'update', 'show', 'destroy'])) { $call .= ', $' . Str::camel($context); diff --git a/src/Lexers/ControllerLexer.php b/src/Lexers/ControllerLexer.php index d67af6e5..bfd9c446 100644 --- a/src/Lexers/ControllerLexer.php +++ b/src/Lexers/ControllerLexer.php @@ -66,7 +66,7 @@ private function generateResourceTokens(Controller $controller, array $methods) return str_replace( ['[singular]', '[plural]'], - [Str::lower($model), Str::lower(Str::plural($model))], + [Str::camel($model), Str::camel(Str::plural($model))], $statement ); }), diff --git a/src/Models/Statements/EloquentStatement.php b/src/Models/Statements/EloquentStatement.php index 5cb9fac8..24aa3bba 100644 --- a/src/Models/Statements/EloquentStatement.php +++ b/src/Models/Statements/EloquentStatement.php @@ -40,12 +40,12 @@ public function output(string $controller_prefix, string $context): string if ($this->operation() == 'save') { if ($context === 'store') { - $code = "$" . Str::lower($model); + $code = "$" . Str::camel($model); $code .= ' = '; $code .= $model; $code .= '::create($request->all());'; } else { - $code = "$" . Str::lower($model) . '->save();'; + $code = "$" . Str::camel($model) . '->save();'; } } @@ -54,7 +54,7 @@ public function output(string $controller_prefix, string $context): string $model = $this->extractModel(); } - $code = "$" . Str::lower($model); + $code = "$" . Str::camel($model); $code .= ' = '; $code .= $model; $code .= '::find($' . $this->columnName($this->reference()) . ');'; @@ -66,7 +66,7 @@ public function output(string $controller_prefix, string $context): string $code .= '::destroy($' . str_replace('.', '->', $this->reference()) . ');'; } else { // TODO: only for certain contexts or no matter what given simple reference? - $code = "$" . Str::lower($model) . '->delete();'; + $code = "$" . Str::camel($model) . '->delete();'; } } diff --git a/src/Models/Statements/QueryStatement.php b/src/Models/Statements/QueryStatement.php index dde12b14..f0d11fc8 100644 --- a/src/Models/Statements/QueryStatement.php +++ b/src/Models/Statements/QueryStatement.php @@ -53,9 +53,9 @@ public function output(string $controller): string if ($this->operation() === 'all') { if (is_null($this->model())) { - return '$' . Str::lower(Str::plural($model)) . ' = ' . $model . '::all();'; + return '$' . Str::camel(Str::plural($model)) . ' = ' . $model . '::all();'; } else { - return '$' . Str::lower($this->clauses()[0]) . ' = ' . $this->model() . '::all();'; + return '$' . Str::camel($this->clauses()[0]) . ' = ' . $this->model() . '::all();'; } } @@ -82,9 +82,9 @@ public function output(string $controller): string if ($this->operation() === 'pluck') { $variable_name = $this->pluckName($pluck_field); } elseif ($this->operation() === 'count') { - $variable_name = Str::lower($model) . '_count'; + $variable_name = Str::camel($model) . '_count'; } else { - $variable_name = Str::lower(Str::plural($model)); + $variable_name = Str::camel(Str::plural($model)); } $code = '$' . $variable_name . ' = ' . $model . '::'; diff --git a/tests/Feature/Generator/ControllerGeneratorTest.php b/tests/Feature/Generator/ControllerGeneratorTest.php index 0a88e22d..13d1c369 100644 --- a/tests/Feature/Generator/ControllerGeneratorTest.php +++ b/tests/Feature/Generator/ControllerGeneratorTest.php @@ -70,6 +70,39 @@ public function output_writes_migration_for_controller_tree($definition, $path, $this->assertEquals(['created' => [$path]], $this->subject->output($tree)); } + /** + * @test + */ + public function output_works_for_pascal_case_definition() + { + $this->files->expects('stub') + ->with('controller/class.stub') + ->andReturn(file_get_contents('stubs/controller/class.stub')); + $this->files->expects('stub') + ->with('controller/method.stub') + ->andReturn(file_get_contents('stubs/controller/method.stub')) + ->twice(); + + $certificateController = 'app/Http/Controllers/CertificateController.php'; + $certificateTypeController = 'app/Http/Controllers/CertificateTypeController.php'; + + $this->files->expects('exists') + ->with(dirname($certificateController)) + ->andReturnTrue(); + $this->files->expects('put') + ->with($certificateController, $this->fixture('controllers/certificate-controller.php')); + + $this->files->expects('exists') + ->with(dirname($certificateTypeController)) + ->andReturnTrue(); + $this->files->expects('put') + ->with($certificateTypeController, $this->fixture('controllers/certificate-type-controller.php')); + + $tokens = $this->blueprint->parse($this->fixture('definitions/pascal-case.bp')); + $tree = $this->blueprint->analyze($tokens); + $this->assertEquals(['created' => [$certificateController, $certificateTypeController]], $this->subject->output($tree)); + } + /** * @test */ diff --git a/tests/Feature/Generator/ModelGeneratorTest.php b/tests/Feature/Generator/ModelGeneratorTest.php index a79a8a50..6437af90 100644 --- a/tests/Feature/Generator/ModelGeneratorTest.php +++ b/tests/Feature/Generator/ModelGeneratorTest.php @@ -91,6 +91,48 @@ public function output_generates_models($definition, $path, $model) $this->assertEquals(['created' => [$path]], $this->subject->output($tree)); } + /** + * @test + */ + public function output_works_for_pascal_case_definition() + { + $this->files->expects('stub') + ->with('model/class.stub') + ->andReturn(file_get_contents('stubs/model/class.stub')); + $this->files->expects('stub') + ->with('model/fillable.stub') + ->andReturn(file_get_contents('stubs/model/fillable.stub')) + ->twice(); + $this->files->expects('stub') + ->with('model/casts.stub') + ->andReturn(file_get_contents('stubs/model/casts.stub')) + ->twice(); + $this->files->expects('stub') + ->with('model/method.stub') + ->andReturn(file_get_contents('stubs/model/method.stub')) + ->twice(); + + $certificateModel = 'app/Certificate.php'; + $certificateTypeModel = 'app/CertificateType.php'; + + $this->files->expects('exists') + ->with(dirname($certificateModel)) + ->andReturnTrue(); + $this->files->expects('put') + ->with($certificateModel, $this->fixture('models/certificate-pascal-case-example.php')); + + $this->files->expects('exists') + ->with(dirname($certificateTypeModel)) + ->andReturnTrue(); + $this->files->expects('put') + ->with($certificateTypeModel, $this->fixture('models/certificate-type-pascal-case-example.php')); + + $tokens = $this->blueprint->parse($this->fixture('definitions/pascal-case.bp')); + $tree = $this->blueprint->analyze($tokens); + + $this->assertEquals(['created' => [$certificateModel, $certificateTypeModel]], $this->subject->output($tree)); + } + /** * @test */ diff --git a/tests/Feature/Generator/TestGeneratorTest.php b/tests/Feature/Generator/TestGeneratorTest.php index b85a54e4..f6f34ada 100644 --- a/tests/Feature/Generator/TestGeneratorTest.php +++ b/tests/Feature/Generator/TestGeneratorTest.php @@ -74,6 +74,39 @@ public function output_generates_test_for_controller_tree($definition, $path, $t $this->assertEquals(['created' => [$path]], $this->subject->output($tree)); } + /** + * @test + */ + public function output_works_for_pascal_case_definition() + { + $this->files->expects('get') + ->with('stubs/test/class.stub') + ->andReturn(file_get_contents('stubs/test/class.stub')); + + $this->files->expects('get') + ->with('stubs/test/case.stub') + ->andReturn(file_get_contents('stubs/test/case.stub')); + + $certificateControllerTest = 'tests/Feature/Http/Controllers/CertificateControllerTest.php'; + $certificateTypeControllerTest = 'tests/Feature/Http/Controllers/CertificateTypeControllerTest.php'; + + $this->files->expects('exists') + ->with(dirname($certificateControllerTest)) + ->andReturnTrue(); + $this->files->expects('put') + ->with($certificateControllerTest, $this->fixture('tests/certificate-pascal-case-example.php')); + + $this->files->expects('exists') + ->with(dirname($certificateTypeControllerTest)) + ->andReturnTrue(); + $this->files->expects('put') + ->with($certificateTypeControllerTest, $this->fixture('tests/certificate-type-pascal-case-example.php')); + + $tokens = $this->blueprint->parse($this->fixture('definitions/pascal-case.bp')); + $tree = $this->blueprint->analyze($tokens); + $this->assertEquals(['created' => [$certificateControllerTest, $certificateTypeControllerTest]], $this->subject->output($tree)); + } + /** * @test */ diff --git a/tests/fixtures/controllers/certificate-controller.php b/tests/fixtures/controllers/certificate-controller.php new file mode 100644 index 00000000..19800213 --- /dev/null +++ b/tests/fixtures/controllers/certificate-controller.php @@ -0,0 +1,67 @@ +all()); + + return new CertificateResource($certificate); + } + + /** + * @param \Illuminate\Http\Request $request + * @param \App\Certificate $certificate + * @return \App\Http\Resources\Certificate + */ + public function show(Request $request, Certificate $certificate) + { + return new CertificateResource($certificate); + } + + /** + * @param \App\Http\Requests\CertificateUpdateRequest $request + * @param \App\Certificate $certificate + * @return \App\Http\Resources\Certificate + */ + public function update(CertificateUpdateRequest $request, Certificate $certificate) + { + return new CertificateResource($certificate); + } + + /** + * @param \Illuminate\Http\Request $request + * @param \App\Certificate $certificate + * @return \Illuminate\Http\Response + */ + public function destroy(Request $request, Certificate $certificate) + { + $certificate->delete(); + + return response()->noContent(200); + } +} diff --git a/tests/fixtures/controllers/certificate-type-controller.php b/tests/fixtures/controllers/certificate-type-controller.php new file mode 100644 index 00000000..842d5e7a --- /dev/null +++ b/tests/fixtures/controllers/certificate-type-controller.php @@ -0,0 +1,67 @@ +all()); + + return new CertificateTypeResource($certificateType); + } + + /** + * @param \Illuminate\Http\Request $request + * @param \App\CertificateType $certificateType + * @return \App\Http\Resources\CertificateType + */ + public function show(Request $request, CertificateType $certificateType) + { + return new CertificateTypeResource($certificateType); + } + + /** + * @param \App\Http\Requests\CertificateTypeUpdateRequest $request + * @param \App\CertificateType $certificateType + * @return \App\Http\Resources\CertificateType + */ + public function update(CertificateTypeUpdateRequest $request, CertificateType $certificateType) + { + return new CertificateTypeResource($certificateType); + } + + /** + * @param \Illuminate\Http\Request $request + * @param \App\CertificateType $certificateType + * @return \Illuminate\Http\Response + */ + public function destroy(Request $request, CertificateType $certificateType) + { + $certificateType->delete(); + + return response()->noContent(200); + } +} diff --git a/tests/fixtures/definitions/pascal-case.bp b/tests/fixtures/definitions/pascal-case.bp new file mode 100644 index 00000000..d6b8c54f --- /dev/null +++ b/tests/fixtures/definitions/pascal-case.bp @@ -0,0 +1,18 @@ +models: + Certificate: + name: string + certificate_type_id: id + reference: string + document: string + expiry_date: date + remarks: nullable text + CertificateType: + name: string + relationships: + hasMany: Certificate + +controllers: + Certificate: + resource: api + CertificateType: + resource: api diff --git a/tests/fixtures/models/certificate-pascal-case-example.php b/tests/fixtures/models/certificate-pascal-case-example.php new file mode 100644 index 00000000..3da041cd --- /dev/null +++ b/tests/fixtures/models/certificate-pascal-case-example.php @@ -0,0 +1,38 @@ + 'integer', + 'certificate_type_id' => 'integer', + ]; + + + public function certificateType() + { + return $this->belongsTo(\App\CertificateType::class); + } +} diff --git a/tests/fixtures/models/certificate-type-pascal-case-example.php b/tests/fixtures/models/certificate-type-pascal-case-example.php new file mode 100644 index 00000000..025b3aa4 --- /dev/null +++ b/tests/fixtures/models/certificate-type-pascal-case-example.php @@ -0,0 +1,32 @@ + 'integer', + ]; + + + public function certificates() + { + return $this->hasMany(\App\Certificate::class); + } +} diff --git a/tests/fixtures/tests/certificate-pascal-case-example.php b/tests/fixtures/tests/certificate-pascal-case-example.php new file mode 100644 index 00000000..64c06a32 --- /dev/null +++ b/tests/fixtures/tests/certificate-pascal-case-example.php @@ -0,0 +1,110 @@ +create(); + + $response = $this->get(route('certificate.index')); + } + + + /** + * @test + */ + public function store_uses_form_request_validation() + { + $this->assertActionUsesFormRequest( + \App\Http\Controllers\CertificateController::class, + 'store', + \App\Http\Requests\CertificateStoreRequest::class + ); + } + + /** + * @test + */ + public function store_saves() + { + $certificate = $this->faker->word; + + $response = $this->post(route('certificate.store'), [ + 'certificate' => $certificate, + ]); + + $certificates = Certificate::query() + ->where('certificate', $certificate) + ->get(); + $this->assertCount(1, $certificates); + $certificate = $certificates->first(); + } + + + /** + * @test + */ + public function show_behaves_as_expected() + { + $certificate = factory(Certificate::class)->create(); + + $response = $this->get(route('certificate.show', $certificate)); + } + + + /** + * @test + */ + public function update_uses_form_request_validation() + { + $this->assertActionUsesFormRequest( + \App\Http\Controllers\CertificateController::class, + 'update', + \App\Http\Requests\CertificateUpdateRequest::class + ); + } + + /** + * @test + */ + public function update_behaves_as_expected() + { + $certificate = factory(Certificate::class)->create(); + $certificate = $this->faker->word; + + $response = $this->put(route('certificate.update', $certificate), [ + 'certificate' => $certificate, + ]); + } + + + /** + * @test + */ + public function destroy_deletes_and_responds_with() + { + $certificate = factory(Certificate::class)->create(); + + $response = $this->delete(route('certificate.destroy', $certificate)); + + $response->assertOk(); + + $this->assertDeleted($certificate); + } +} diff --git a/tests/fixtures/tests/certificate-type-pascal-case-example.php b/tests/fixtures/tests/certificate-type-pascal-case-example.php new file mode 100644 index 00000000..446545a8 --- /dev/null +++ b/tests/fixtures/tests/certificate-type-pascal-case-example.php @@ -0,0 +1,110 @@ +create(); + + $response = $this->get(route('certificate-type.index')); + } + + + /** + * @test + */ + public function store_uses_form_request_validation() + { + $this->assertActionUsesFormRequest( + \App\Http\Controllers\CertificateTypeController::class, + 'store', + \App\Http\Requests\CertificateTypeStoreRequest::class + ); + } + + /** + * @test + */ + public function store_saves() + { + $certificateType = $this->faker->word; + + $response = $this->post(route('certificate-type.store'), [ + 'certificateType' => $certificateType, + ]); + + $certificateTypes = CertificateType::query() + ->where('certificateType', $certificateType) + ->get(); + $this->assertCount(1, $certificateTypes); + $certificateType = $certificateTypes->first(); + } + + + /** + * @test + */ + public function show_behaves_as_expected() + { + $certificateType = factory(CertificateType::class)->create(); + + $response = $this->get(route('certificate-type.show', $certificateType)); + } + + + /** + * @test + */ + public function update_uses_form_request_validation() + { + $this->assertActionUsesFormRequest( + \App\Http\Controllers\CertificateTypeController::class, + 'update', + \App\Http\Requests\CertificateTypeUpdateRequest::class + ); + } + + /** + * @test + */ + public function update_behaves_as_expected() + { + $certificateType = factory(CertificateType::class)->create(); + $certificateType = $this->faker->word; + + $response = $this->put(route('certificate-type.update', $certificateType), [ + 'certificateType' => $certificateType, + ]); + } + + + /** + * @test + */ + public function destroy_deletes_and_responds_with() + { + $certificateType = factory(CertificateType::class)->create(); + + $response = $this->delete(route('certificate-type.destroy', $certificateType)); + + $response->assertOk(); + + $this->assertDeleted($certificateType); + } +}