You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
4.1 KiB

2 years ago
  1. <?php
  2. namespace App\Console\Commands;
  3. use Database\Factories\BaseFactory;
  4. use Illuminate\Console\Command;
  5. use Illuminate\Support\Facades\File;
  6. class TestGenerator extends Command
  7. {
  8. const MODELS_NAMESPACE = 'App\\Models\\';
  9. const BASE_FACTORY_TRAIT = 'Database\Factories\BaseFactory';
  10. /**
  11. * The name and signature of the console command.
  12. *
  13. * @var string
  14. */
  15. protected $signature = 'generate:test {models?}';
  16. /**
  17. * The console command description.
  18. *
  19. * @var string
  20. */
  21. protected $description = 'Generate test for requested model name';
  22. /**
  23. * Create a new command instance.
  24. *
  25. * @return void
  26. */
  27. public function __construct()
  28. {
  29. parent::__construct();
  30. }
  31. /**
  32. * Execute the console command.
  33. *
  34. * @return void
  35. * @throws \Throwable
  36. */
  37. public function handle()
  38. {
  39. $models = $this->getSelectedModels();
  40. // if (!is_dir('tests/Feature/' . ucfirst($model))) {
  41. // mkdir('tests/Feature/' . ucfirst($model), 0777, true);
  42. // } else {
  43. // $confirm = $this->confirm("$model tests before created, are you sure delete them and regenerate test?", true);
  44. // if ($confirm) {
  45. // system("rm -rf " . escapeshellarg('tests/Feature/' . ucfirst($model)));
  46. // mkdir('tests/Feature/' . ucfirst($model), 0777, true);
  47. // }
  48. // }
  49. foreach ($models as $model) {
  50. $className = str_replace(self::MODELS_NAMESPACE, '', $model);
  51. foreach (['store', 'update', 'show', 'delete'] as $test_name) {
  52. $options = (new $model())->factory()->testGeneratorConfig()[$test_name] ?? null;
  53. if ($options === null) {
  54. continue;
  55. }
  56. //todo:need work
  57. file_put_contents(
  58. 'tests/Feature/' . ucfirst($className) . '/' . ucfirst($className) . ucfirst($test_name) . 'Test.php',
  59. view(
  60. 'tests.' . $test_name,
  61. [
  62. 'model' => new $model(),
  63. 'sol' => "<?php",
  64. 'profile' => null,
  65. 'auth' => null,
  66. ])->render()
  67. );
  68. $this->info("Generate " . ucfirst($className) . ucfirst($test_name) . 'Test.php successfully!');
  69. }
  70. }
  71. $this->info("\nGo enjoy it :) Powered with ❤️ from Haj Mehdi And Masoud Productions (registered trademark).");
  72. }
  73. /**
  74. * @return \Illuminate\Support\Collection
  75. * @throws \Throwable
  76. */
  77. private function getSelectedModels()
  78. {
  79. $models = $this->argument('models');
  80. $models = empty($models) ?
  81. $this->getAllModels() :
  82. collect(explode(',', $models));
  83. return $models->map(fn($m) => self::MODELS_NAMESPACE . $m)->each(function ($model) {
  84. $className = str_replace(self::MODELS_NAMESPACE, '', $model);
  85. throw_if(!class_exists($model), $model . ' Not exists!');
  86. throw_if(!$this->passRequirements(new $model), $className . 'Factory must have list, testGeneratorConfig and dependencyProvider functions');
  87. throw_if(!$this->hasBaseFactoryTrait(new $model), $className . 'Factory use BaseFactory trait.');
  88. })->toArray();
  89. }
  90. private function getAllModels()
  91. {
  92. $models = [];
  93. $path = app_path('Models');
  94. $files = File::files($path);
  95. foreach ($files as $file) {
  96. $models [] = str_replace('.php', '', $file->getFileName());
  97. }
  98. return collect($models);
  99. }
  100. public function passRequirements($model)
  101. {
  102. return
  103. method_exists($model->factory(), 'list') &&
  104. method_exists($model->factory(), 'testGeneratorConfig') &&
  105. method_exists($model->factory(), 'dependencyProvider');
  106. }
  107. /**
  108. * @param $model
  109. * @return false
  110. * @throws \ReflectionException
  111. */
  112. public function hasBaseFactoryTrait($model)
  113. {
  114. return in_array(
  115. BaseFactory::class,
  116. array_keys((new \ReflectionClass(($model)->factory()))->getTraits())
  117. );
  118. }
  119. }