Skip to content

Commit

Permalink
Aligned Tests and improved installation process
Browse files Browse the repository at this point in the history
  • Loading branch information
coolsam726 committed Apr 10, 2024
1 parent ddc39cd commit 6a2a83a
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 97 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:
strategy:
fail-fast: true
matrix:
os: [ubuntu-latest, windows-latest]
php: [8.2, 8.3]
laravel: [11.*]
stability: [prefer-lowest, prefer-stable]
os: [ ubuntu-latest, windows-latest ]
php: [ 8.2, 8.3 ]
laravel: [ 11.* ]
stability: [ prefer-lowest, prefer-stable ]
include:
- laravel: 11.*
testbench: 9.*
Expand All @@ -36,7 +36,7 @@ jobs:
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
coverage: none
coverage: pcov

- name: Setup problem matchers
run: |
Expand Down
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ phpstan.neon
testbench.yaml
vendor
node_modules
./skeleton
./workbench
./modules
skeleton
workbench
modules
30 changes: 21 additions & 9 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,20 @@
"autoload-dev": {
"psr-4": {
"Savannabits\\Modular\\Tests\\": "tests/",
"Workbench\\App\\": "workbench/app/"
"Workbench\\App\\": "workbench/app/",
"Workbench\\Database\\Factories\\": "workbench/database/factories/",
"Workbench\\Database\\Seeders\\": "workbench/database/seeders/"
}
},
"scripts": {
"post-autoload-dump": "@composer run prepare",
"clear": "@php vendor/bin/testbench package:purge-modular --ansi",
"prepare": "@php vendor/bin/testbench package:discover --ansi",
"build": [
"@composer run prepare",
"@php vendor/bin/testbench workbench:build --ansi"
"post-autoload-dump": [
"@clear",
"@prepare",
"@composer run prepare"
],
"clear": "@php vendor/bin/testbench package:purge-skeleton --ansi",
"prepare": "@php vendor/bin/testbench package:discover --ansi",
"build": "@php vendor/bin/testbench workbench:build --ansi",
"start": [
"Composer\\Config::disableProcessTimeout",
"@composer run build",
Expand All @@ -61,7 +64,16 @@
"analyse": "vendor/bin/phpstan analyse",
"test": "vendor/bin/pest",
"test-coverage": "vendor/bin/pest --coverage",
"format": "vendor/bin/pint"
"format": "vendor/bin/pint",
"serve": [
"Composer\\Config::disableProcessTimeout",
"@build",
"@php vendor/bin/testbench serve"
],
"lint": [
"@php vendor/bin/pint",
"@php vendor/bin/phpstan analyse"
]
},
"config": {
"sort-packages": true,
Expand All @@ -82,4 +94,4 @@
},
"minimum-stability": "dev",
"prefer-stable": true
}
}
7 changes: 5 additions & 2 deletions src/Commands/ModuleActivateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Savannabits\Modular\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Str;
use Savannabits\Modular\Facades\Modular;

Expand All @@ -27,7 +28,9 @@ private function activateModule(): void
{
$moduleName = $this->moduleName;
$repoName = config('modular.vendor', 'modular').'/'.$moduleName;
Modular::execCommand('composer require '.$repoName.':@dev');
Modular::execCommand("php artisan $moduleName:install");
Modular::execCommand('composer require '.$repoName.':@dev', $this);
Modular::execCommand('composer dump-autoload');
Artisan::call('list');
Artisan::call("$moduleName:install");
}
}
58 changes: 41 additions & 17 deletions src/Commands/ModuleMakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
use Illuminate\Support\Str;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Savannabits\Modular\Facades\Modular;
use Savannabits\Modular\Support\Concerns\CanManipulateFiles;

use function Laravel\Prompts\confirm;
use function Laravel\Prompts\text;

class ModuleMakeCommand extends Command
Expand Down Expand Up @@ -40,9 +40,27 @@ public function handle()
$this->modulePath = config('modular.path').'/'.$this->moduleName;
$this->info("Creating module: $this->moduleName in $this->modulePath");

$this->generateModuleDirectories();
$this->generateModuleFiles();
$this->installModule();
if (! $this->generateModuleDirectories()) {
$this->error('Failed to create module directories');

return 1;
}
if (! $this->generateModuleFiles()) {
$this->error('Failed to create module files');

return 1;
}

// Ask if to install the new module
if (confirm('Do you want to activate the new module now?', false, required: true)) {
if (! $this->installModule()) {
$this->error('Failed to activate the new module');

return 1;
}
}

return 0;
}

private function generateModuleDirectories(): bool
Expand All @@ -53,6 +71,12 @@ private function generateModuleDirectories(): bool

return false;
}
// If the module exists and force option is not set, confirm that you want to override files
if (is_dir($this->modulePath) && ! $this->option('force')) {
if (! confirm('Module already exists. Do you want to override it?')) {
return false;
}
}
foreach ($directories as $directory) {
$path = $this->modulePath.'/'.ltrim($directory, '/');
if (! is_dir($path)) {
Expand All @@ -65,15 +89,13 @@ private function generateModuleDirectories(): bool
return true;
}

private function generateModuleFiles(): void
private function generateModuleFiles(): bool
{
$this->generateModuleComposerFile();
try {
$this->generateModuleServiceProvider();
} catch (FileNotFoundException|NotFoundExceptionInterface|ContainerExceptionInterface $e) {
$this->error($e->getMessage());
}
$this->generateModuleServiceProvider();
$this->generatePestFiles();

return true;
}

private function generateModuleComposerFile(): void
Expand Down Expand Up @@ -124,7 +146,9 @@ private function generateModuleComposerFile(): void
*/
private function generateModuleServiceProvider(): void
{
$path = Modular::module($this->moduleName)->appPath($this->moduleStudlyName.'ServiceProvider.php');
$this->comment('Generating Module Service Provider');
// get the path to the service provider
$path = $this->modulePath.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.$this->moduleStudlyName.'ServiceProvider.php';
$namespace = $this->moduleNamespace;
$class = $this->moduleStudlyName.'ServiceProvider';
$this->copyStubToApp('module.provider', $path, [
Expand All @@ -137,29 +161,29 @@ private function generateModuleServiceProvider(): void
private function generatePestFiles(): void
{
// phpunit.xml
$path = Modular::module($this->moduleName)->path('phpunit.xml');
$path = $this->modulePath.DIRECTORY_SEPARATOR.'phpunit.xml';
$this->copyStubToApp('phpunit', $path, [
'moduleName' => $this->moduleStudlyName,
]);

// Pest.php
$path = Modular::module($this->moduleName)->testsPath('Pest.php');
$path = $this->modulePath.DIRECTORY_SEPARATOR.'tests'.DIRECTORY_SEPARATOR.'Pest.php';
$this->copyStubToApp('pest.class', $path, [
'namespace' => $this->moduleNamespace,
]);

// TestCase.php
$path = Modular::module($this->moduleName)->testsPath('TestCase.php');
$path = $this->modulePath.DIRECTORY_SEPARATOR.'tests'.DIRECTORY_SEPARATOR.'TestCase.php';
$this->copyStubToApp('test-case', $path, [
'namespace' => $this->moduleNamespace.'\\Tests',
]);
}



private function installModule(): void
private function installModule(): bool
{
$this->comment('Activating the new Module');
$this->call('modular:activate', ['name' => $this->moduleName]);

return true;
}
}
16 changes: 12 additions & 4 deletions src/Modular.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@

namespace Savannabits\Modular;

use Illuminate\Console\Command;
use Symfony\Component\Process\Process;

class Modular
{
public function execCommand(string $command): void
public function execCommand(string $command, ?Command $artisan = null): void
{
$process = proc_open($command, [STDIN, STDOUT, STDERR], $pipes, base_path());
if (is_resource($process)) {
proc_close($process);
$process = Process::fromShellCommandline($command);
$process->start();
foreach ($process as $type => $data) {
if (! $artisan) {
echo $data;
} else {
$artisan->info(trim($data));
}
}
}

Expand Down
34 changes: 5 additions & 29 deletions src/ModularServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ public function configurePackage(Package $package): void
$this->mergeConfigFrom($this->package->basePath('/../config/modular.php'), 'modular');
}

private function configureComposerMerge(InstallCommand $command): void
private function configureComposerFile(InstallCommand $command): void
{
$command->comment('Configuring Composer merge plugin:');
$command->comment('Configuring Composer File:');
$composerJson = json_decode(file_get_contents(base_path('composer.json')), true);
// Add the modules repositories into compose if they don't exist
if (! isset($composerJson['repositories'])) {
Expand All @@ -56,41 +56,17 @@ private function configureComposerMerge(InstallCommand $command): void
],
];
}
if (! isset($composerJson['extra']['merge-plugin'])) {
$composerJson['extra']['merge-plugin'] = [
'include' => [
'modules/*/composer.json',
],
'replace' => true,
'merge-extra' => true,
'merge-extra-deep' => true,
'merge-scripts' => true,

];

// Ensure the composer-merge-plugin is in the list of allowed plugins
if (! isset($composerJson['config']['allow-plugins'])) {
$composerJson['config']['allow-plugins'] = [];
}
// If allowed-plugins is set to true, disregard
if ($composerJson['config']['allow-plugins'] === true) {
$command->warn('Composer merge plugin already configured. skipping...');
} else {
$composerJson['config']['allow-plugins']['wikimedia/composer-merge-plugin'] = true;
}
}
file_put_contents(base_path('composer.json'), json_encode($composerJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
$command->info('Composer file configured successfully');
}

private function installationSteps(InstallCommand $command): void
{
$this->ensureModularPathExists($command);
$this->configureComposerMerge($command);
// Run composer dump-autoload and pipe the output realtime
$command->comment('Running composer dump-autoload:');
$this->configureComposerFile($command);
/*$command->comment('Running composer dump-autoload:');
\Savannabits\Modular\Facades\Modular::execCommand('composer dump-autoload');
$command->info('Composer dump-autoload completed successfully');
$command->info('Composer dump-autoload completed successfully');*/
}

private function ensureModularPathExists(InstallCommand $command): void
Expand Down
28 changes: 25 additions & 3 deletions tests/Feature/ModuleCreationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,31 @@

use function Pest\Laravel\artisan;

beforeEach(function () {
$this->moduleTitle = 'Access Control';
$this->moduleName = 'access-control';
$this->moduleStudlyName = 'AccessControl';
});
test('can generate a new module', function () {
// Run modular:make-module, expect a new module to be created
artisan('modular:make', ['name' => 'Access Control', '--no-interaction' => true])
->expectsOutputToContain('Module created successfully.')
->assertExitCode(0);
artisan('modular:make', ['name' => $this->moduleTitle])
->expectsQuestion('Module already exists. Do you want to override it?', true)
->expectsQuestion('Do you want to activate the new module now?', false);
});

// can activate module
test('can activate a module whose directory exists in modules', function () {
artisan('modular:activate', ['name' => $this->moduleTitle])
->expectsOutput('Activating module: '.$this->moduleName)
->expectsOutput('./composer.json has been updated')
->expectsOutput('Running composer update modular/'.$this->moduleName)
->doesntExpectOutputToContain('Your requirements could not be resolved to an installable set of packages')
->expectsOutputToContain('Generating optimized autoload files')
->assertSuccessful();
});

test('should not override existing module unless the user confirms', function () {
artisan('modular:make', ['name' => $this->moduleTitle])
->expectsQuestion('Module already exists. Do you want to override it?', false)
->expectsOutput('Failed to create module directories');
});
10 changes: 10 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,21 @@
namespace Savannabits\Modular\Tests;

use Illuminate\Database\Eloquent\Factories\Factory;
use Orchestra\Testbench\Concerns\WithWorkbench;
use Orchestra\Testbench\TestCase as Orchestra;
use Savannabits\Modular\ModularServiceProvider;

class TestCase extends Orchestra
{
use WithWorkbench;

/**
* Automatically enables package discoveries.
*
* @var bool
*/
protected $enablesPackageDiscoveries = true;

protected function setUp(): void
{
parent::setUp();
Expand Down
25 changes: 0 additions & 25 deletions workbench/app/Providers/WorkbenchServiceProvider.php

This file was deleted.

0 comments on commit 6a2a83a

Please sign in to comment.