master

laravel/framework

Last updated at: 29/12/2023 09:23

TestMakeCommand.php

TLDR

This file defines the TestMakeCommand class, which is a console command for generating test classes in a Laravel project.

Methods

getStub

This method is responsible for returning the stub file path based on whether the --pest and --unit options are set.

resolveStubPath

This method resolves the fully-qualified path to the stub file.

getPath

This method returns the destination class path based on the given name.

getDefaultNamespace

This method returns the default namespace for the generated class based on the root namespace and the --unit option.

rootNamespace

This method returns the root namespace for the generated class, which is "Tests".

getOptions

This method returns the console command options for the make:test command.

afterPromptingForMissingArguments

This method interacts further with the user if there are missing arguments, prompting the user to choose the type of test to be generated.

Classes

TestMakeCommand

This class extends the GeneratorCommand class and represents a console command for generating test classes. It sets the necessary properties for the command, such as the name, description, and type of class. It also overrides several methods for customizing the generation process.

<?php

namespace Illuminate\Foundation\Console;

use Illuminate\Console\GeneratorCommand;
use Illuminate\Support\Str;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

use function Laravel\Prompts\select;

#[AsCommand(name: 'make:test')]
class TestMakeCommand extends GeneratorCommand
{
    /**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'make:test';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create a new test class';

    /**
     * The type of class being generated.
     *
     * @var string
     */
    protected $type = 'Test';

    /**
     * Get the stub file for the generator.
     *
     * @return string
     */
    protected function getStub()
    {
        $suffix = $this->option('unit') ? '.unit.stub' : '.stub';

        return $this->option('pest')
            ? $this->resolveStubPath('/stubs/pest'.$suffix)
            : $this->resolveStubPath('/stubs/test'.$suffix);
    }

    /**
     * Resolve the fully-qualified path to the stub.
     *
     * @param  string  $stub
     * @return string
     */
    protected function resolveStubPath($stub)
    {
        return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
                        ? $customPath
                        : __DIR__.$stub;
    }

    /**
     * Get the destination class path.
     *
     * @param  string  $name
     * @return string
     */
    protected function getPath($name)
    {
        $name = Str::replaceFirst($this->rootNamespace(), '', $name);

        return base_path('tests').str_replace('\\', '/', $name).'.php';
    }

    /**
     * Get the default namespace for the class.
     *
     * @param  string  $rootNamespace
     * @return string
     */
    protected function getDefaultNamespace($rootNamespace)
    {
        if ($this->option('unit')) {
            return $rootNamespace.'\Unit';
        } else {
            return $rootNamespace.'\Feature';
        }
    }

    /**
     * Get the root namespace for the class.
     *
     * @return string
     */
    protected function rootNamespace()
    {
        return 'Tests';
    }

    /**
     * Get the console command options.
     *
     * @return array
     */
    protected function getOptions()
    {
        return [
            ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the test already exists'],
            ['unit', 'u', InputOption::VALUE_NONE, 'Create a unit test'],
            ['pest', 'p', InputOption::VALUE_NONE, 'Create a Pest test'],
        ];
    }

    /**
     * Interact further with the user if they were prompted for missing arguments.
     *
     * @param  \Symfony\Component\Console\Input\InputInterface  $input
     * @param  \Symfony\Component\Console\Output\OutputInterface  $output
     * @return void
     */
    protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output)
    {
        if ($this->isReservedName($this->getNameInput()) || $this->didReceiveOptions($input)) {
            return;
        }

        $type = select('Which type of test would you like?', [
            'feature' => 'Feature (PHPUnit)',
            'unit' => 'Unit (PHPUnit)',
            'pest-feature' => 'Feature (Pest)',
            'pest-unit' => 'Unit (Pest)',
        ]);

        match ($type) {
            'feature' => null,
            'unit' => $input->setOption('unit', true),
            'pest-feature' => $input->setOption('pest', true),
            'pest-unit' => tap($input)->setOption('pest', true)->setOption('unit', true),
        };
    }
}