From 4155eef8dc63bf41c35e36c2ba775660ee8a03b4 Mon Sep 17 00:00:00 2001 From: Mohammad Alavi Date: Wed, 1 Jan 2025 19:18:32 +0330 Subject: [PATCH] wip --- src/Abstract/Providers/ServiceProvider.php | 9 ++ src/Foundation/{Loaders => }/Apiato.php | 123 ++++++++++++++---- .../Configuration/ApplicationBuilder.php | 60 +++++++++ src/Foundation/Configuration/Localization.php | 52 ++++++++ src/Foundation/Loaders/ApplicationBuilder.php | 54 -------- src/Foundation/Loaders/HelperLoader.php | 29 +++++ .../Loaders/LanguageLoaderTrait.php | 38 ------ src/Foundation/Loaders/Loader.php | 8 ++ .../Providers/ApiatoServiceProvider.php | 71 +++++----- .../Providers/MacroServiceProvider.php | 4 +- src/Foundation/Support/PathHelper.php | 33 ++++- .../Providers/LocalizationServiceProvider.php | 18 +++ src/Generator/GeneratorsServiceProvider.php | 4 +- src/Generator/Stubs/providers/generic.stub | 2 +- .../Providers/ApiatoServiceProviderTest.php | 76 ++--------- .../Providers/ConfigurationTest.php | 18 +-- .../MySection/Book/Languages/en/errors.php | 5 + .../MySection/Book/Languages/fa/errors.php | 5 + .../MySection/Book/Languages/fr.json | 3 + .../Laravel/app/Ship/Languages/en/errors.php | 5 + .../Laravel/app/Ship/Languages/fa/errors.php | 5 + .../Fakes/Laravel/app/Ship/Languages/fr.json | 3 + .../Doubles/Fakes/Laravel/bootstrap/app.php | 5 +- .../Doubles/Fakes/Laravel/composer.json | 5 - tests/Unit/Foundation/ApiatoTest.php | 35 +++++ .../Configuration/LocalizationTest.php | 38 ++++++ .../Foundation/Loaders/HelperLoaderTest.php | 13 ++ .../Providers/MacroServiceProviderTest.php | 0 .../Foundation/Support/PathHelperTest.php | 2 +- .../LocalizationServiceProviderTest.php | 30 +++++ 30 files changed, 497 insertions(+), 256 deletions(-) create mode 100644 src/Abstract/Providers/ServiceProvider.php rename src/Foundation/{Loaders => }/Apiato.php (62%) create mode 100644 src/Foundation/Configuration/ApplicationBuilder.php create mode 100644 src/Foundation/Configuration/Localization.php delete mode 100644 src/Foundation/Loaders/ApplicationBuilder.php create mode 100644 src/Foundation/Loaders/HelperLoader.php delete mode 100644 src/Foundation/Loaders/LanguageLoaderTrait.php create mode 100644 src/Foundation/Loaders/Loader.php create mode 100644 src/Foundation/Support/Providers/LocalizationServiceProvider.php create mode 100644 tests/Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages/en/errors.php create mode 100644 tests/Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages/fa/errors.php create mode 100644 tests/Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages/fr.json create mode 100644 tests/Support/Doubles/Fakes/Laravel/app/Ship/Languages/en/errors.php create mode 100644 tests/Support/Doubles/Fakes/Laravel/app/Ship/Languages/fa/errors.php create mode 100644 tests/Support/Doubles/Fakes/Laravel/app/Ship/Languages/fr.json create mode 100644 tests/Unit/Foundation/ApiatoTest.php create mode 100644 tests/Unit/Foundation/Configuration/LocalizationTest.php create mode 100644 tests/Unit/Foundation/Loaders/HelperLoaderTest.php rename tests/Unit/Foundation/{Support => }/Providers/MacroServiceProviderTest.php (100%) create mode 100644 tests/Unit/Foundation/Support/Providers/LocalizationServiceProviderTest.php diff --git a/src/Abstract/Providers/ServiceProvider.php b/src/Abstract/Providers/ServiceProvider.php new file mode 100644 index 000000000..fb8c019c5 --- /dev/null +++ b/src/Abstract/Providers/ServiceProvider.php @@ -0,0 +1,9 @@ + $basePath, + default => self::inferBasePath(), + }; + + self::$instance = new self($basePath); - return (new ApplicationBuilder()) + return (new ApplicationBuilder(self::$instance)) ->withProviders( $basePath . '/app/Ship/Providers', ...glob($basePath . '/app/Containers/*/*/Providers', GLOB_ONLYDIR | GLOB_NOSORT), @@ -36,45 +55,95 @@ public static function configure(string $basePath): ApplicationBuilder )->withCommands( $basePath . '/app/Ship/Commands', ...glob($basePath . '/app/Containers/*/*/UI/Console', GLOB_ONLYDIR | GLOB_NOSORT), - ); + )->withHelpers( + $basePath . '/app/Ship/Helpers', + )->withTranslations(); + } + + /** + * Infer the application's base directory from the environment. + */ + public static function inferBasePath(): string + { + return match (true) { + isset($_ENV['APP_BASE_PATH']) => $_ENV['APP_BASE_PATH'], + default => dirname(array_keys(ClassLoader::getRegisteredLoaders())[0]), + }; + } + + public static function instance(): self + { + return self::$instance; + } + + public function withProviders(string ...$path): self + { + $this->providerPaths = $path; + + return $this; + } + + public function withTranslations(callable|null $callback = null): self + { + $this->localization = (new Localization()) + ->loadTranslationsFrom( + $this->basePath . '/app/Ship/Languages', + ...glob($this->basePath . '/app/Containers/*/*/Languages', GLOB_ONLYDIR | GLOB_NOSORT), + ); + + if (!is_null($callback)) { + $callback($this->localization); + } + + return $this; + } + + public function withConfigs(string ...$path): void + { + $this->configPaths = $path; + } + + public function withEvents(string ...$path): void + { + $this->listenerPaths = $path; } - public static function loadProvidersFrom(string ...$path): void + public function withCommands(string ...$path): void { - self::$providerPaths = $path; + $this->commandPaths = $path; } - public static function loadConfigsFrom(string ...$path): void + public function withHelpers(string ...$path): void { - self::$configPaths = $path; + $this->helperPaths = $path; } - public static function loadEventsFrom(string ...$path): void + public function providerPaths(): array { - self::$listenerPaths = $path; + return $this->providerPaths; } - public static function loadCommandsFrom(string ...$path): void + public function configPaths(): array { - self::$commandPaths = $path; + return $this->configPaths; } - public static function providerPaths(): array + public function helperPaths(): array { - return self::$providerPaths; + return $this->helperPaths; } - public static function configPaths(): array + public function localization(): Localization { - return self::$configPaths; + return $this->localization; } - public static function getListeners(): array + public function events(): array { - return self::$listenerPaths; + return $this->listenerPaths; } - public static function getApiMiddlewares(): array + public function apiMiddlewares(): array { return [ ValidateJsonContent::class, @@ -83,9 +152,9 @@ public static function getApiMiddlewares(): array ]; } - public static function getCommands(): array + public function commands(): array { - return self::$commandPaths; + return $this->commandPaths; } // TODO: separate Api and Web route registration diff --git a/src/Foundation/Configuration/ApplicationBuilder.php b/src/Foundation/Configuration/ApplicationBuilder.php new file mode 100644 index 000000000..21226ede2 --- /dev/null +++ b/src/Foundation/Configuration/ApplicationBuilder.php @@ -0,0 +1,60 @@ +apiato->withProviders(...$path); + + return $this; + } + + public function withConfigs(string ...$path): self + { + $this->apiato->withConfigs(...$path); + + return $this; + } + + public function withEvents(string ...$path): self + { + $this->apiato->withEvents(...$path); + + return $this; + } + + public function withCommands(string ...$path): self + { + $this->apiato->withCommands(...$path); + + return $this; + } + + public function withHelpers(string ...$path): self + { + $this->apiato->withHelpers(...$path); + + return $this; + } + + public function withTranslations(callable|null $callback = null): self + { + $this->apiato->withTranslations($callback); + + return $this; + } + + public function create(): Apiato + { + return $this->apiato; + } +} diff --git a/src/Foundation/Configuration/Localization.php b/src/Foundation/Configuration/Localization.php new file mode 100644 index 000000000..ed82ca595 --- /dev/null +++ b/src/Foundation/Configuration/Localization.php @@ -0,0 +1,52 @@ +buildNamespaceUsing(function ($path): string { + if (Str::contains($path, PathHelper::getSharedDirectoryPath())) { + return Str::camel(PathHelper::getSharedDirectoryName()); + } + + return Str::of($path) + ->after(PathHelper::getContainersDirectoryName() . DIRECTORY_SEPARATOR) + ->explode(DIRECTORY_SEPARATOR) + ->take(2) + ->map(static fn ($part) => Str::camel($part)) + ->implode('@'); + }); + } + + public function buildNamespaceUsing(callable $callback): self + { + self::$namespaceBuilder = $callback; + + return $this; + } + + public function paths(): array + { + return $this->paths; + } + + public function loadTranslationsFrom(string ...$paths): self + { + $this->paths = $paths; + + return $this; + } + + public function buildNamespaceFor(string $path): string + { + return app()->call(self::$namespaceBuilder, compact('path')); + } +} diff --git a/src/Foundation/Loaders/ApplicationBuilder.php b/src/Foundation/Loaders/ApplicationBuilder.php deleted file mode 100644 index 26cbae271..000000000 --- a/src/Foundation/Loaders/ApplicationBuilder.php +++ /dev/null @@ -1,54 +0,0 @@ -registerRoutes(); - } - - public function apiMiddlewares(): array - { - return Apiato::getApiMiddlewares(); - } - - public function commands(): array - { - return (new Apiato())->getCommands(); - } -} diff --git a/src/Foundation/Loaders/HelperLoader.php b/src/Foundation/Loaders/HelperLoader.php new file mode 100644 index 000000000..116990eba --- /dev/null +++ b/src/Foundation/Loaders/HelperLoader.php @@ -0,0 +1,29 @@ +helperPaths()); + } + + public function load(): void + { + foreach ($this->paths as $path) { + $files = File::files($path); + + foreach ($files as $file) { + require_once $file; + } + } + } +} diff --git a/src/Foundation/Loaders/LanguageLoaderTrait.php b/src/Foundation/Loaders/LanguageLoaderTrait.php deleted file mode 100644 index d8ffbefaf..000000000 --- a/src/Foundation/Loaders/LanguageLoaderTrait.php +++ /dev/null @@ -1,38 +0,0 @@ -loadLocals($containerLocaleDirectory, $containerName, $sectionName); - } - - private function loadLocals($directory, $containerName, $sectionName = null): void - { - if (File::isDirectory($directory)) { - $this->loadTranslationsFrom($directory, $this->buildLocaleNamespace($sectionName, $containerName)); - $this->loadJsonTranslationsFrom($directory); - } - } - - private function buildLocaleNamespace(string|null $sectionName, string $containerName): string - { - return $sectionName ? (Str::camel($sectionName) . '@' . Str::camel($containerName)) : Str::camel($containerName); - } - - public function loadShipLanguages(): void - { - $shipLocaleDirectory = base_path('app/Ship/Languages'); - $this->loadLocals($shipLocaleDirectory, 'ship'); - } -} diff --git a/src/Foundation/Loaders/Loader.php b/src/Foundation/Loaders/Loader.php new file mode 100644 index 000000000..cdbaf13c1 --- /dev/null +++ b/src/Foundation/Loaders/Loader.php @@ -0,0 +1,8 @@ +providerPaths() as $directory) { foreach (File::files($directory) as $file) { $fqcn = PathHelper::getFQCNFromFile($file); $providers[] = $fqcn; @@ -68,10 +70,24 @@ private function serviceProviders(): array return $providers; } + private function registerCoreCommands(): void + { + if ($this->app->runningInConsole()) { + $this->commands([ + ListActions::class, + ListTasks::class, + SeedDeploymentData::class, + SeedTestingData::class, + ]); + } + } + + // TODO: can we NOT do this and move the providers in the fake Laravel app? + private function mergeConfigs(): void { // The order of these statements matter! DO NOT CHANGE! - foreach (Apiato::configPaths() as $dir) { + foreach (Apiato::instance()->configPaths() as $dir) { foreach (File::files($dir) as $file) { $this->mergeConfigFrom($file->getPathname(), $file->getFilenameWithoutExtension()); } @@ -83,7 +99,6 @@ private function mergeConfigs(): void ); } - // TODO: can we NOT do this and move the providers in the fake Laravel app? private function setUpTestProviders(Application $app): void { $currentProviders = $this->providers; @@ -101,7 +116,7 @@ public function boot(): void { $this->runBoot(); - $this->runLoadersBoot(); + $this->runLoaders(); $this->publishes([ __DIR__ . '/../../../config/apiato.php' => app_path('Ship/Configs/apiato.php'), @@ -109,7 +124,7 @@ public function boot(): void $this->configureRateLimiting(); // TODO: move to route service provider - // dd(Apiato::create()->getServiceProviders()); + // dd(Apiato::instance()->create()->getServiceProviders()); // dd(app()->getProviders(AggregateServiceProvider::class)); // dd(AliasLoader::getInstance()->getAliases()); // dd(Event::getRawListeners()); @@ -117,20 +132,28 @@ public function boot(): void AboutCommand::add('Apiato', static fn () => ['Version' => '13.0.0']); } - public function runLoadersBoot(): void + public function runLoaders(): void { - $this->loadShipLanguages(); + $this->load( + HelperLoader::create(), + ); + // $this->loadShipMigrations(); // $this->loadShipViews(); - $this->loadShipHelpers(); foreach (PathHelper::getContainerPaths() as $containerPath) { - $this->loadContainerLanguages($containerPath); // $this->loadContainerMigrations($containerPath); // $this->loadContainerViews($containerPath); } } + private function load(Loader ...$loader): void + { + foreach ($loader as $load) { + $load->load(); + } + } + protected function configureRateLimiting(): void { if (config('apiato.api.rate-limiter.enabled')) { @@ -145,28 +168,4 @@ static function (Request $request) { ); } } - - private function loadShipHelpers(): void - { - $shipHelpersDirectory = base_path('app/Ship/Helpers'); - if (File::isDirectory($shipHelpersDirectory)) { - $files = File::files($shipHelpersDirectory); - - foreach ($files as $file) { - require_once $file; - } - } - } - - private function registerCoreCommands(): void - { - if ($this->app->runningInConsole()) { - $this->commands([ - ListActions::class, - ListTasks::class, - SeedDeploymentData::class, - SeedTestingData::class, - ]); - } - } } diff --git a/src/Foundation/Providers/MacroServiceProvider.php b/src/Foundation/Providers/MacroServiceProvider.php index 5249227e5..396fd7827 100644 --- a/src/Foundation/Providers/MacroServiceProvider.php +++ b/src/Foundation/Providers/MacroServiceProvider.php @@ -2,14 +2,14 @@ namespace Apiato\Foundation\Providers; -use Apiato\Abstract\Providers\AggregateServiceProvider; +use Apiato\Abstract\Providers\ServiceProvider; use Illuminate\Config\Repository; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Config; use Vinkla\Hashids\Facades\Hashids; -final class MacroServiceProvider extends AggregateServiceProvider +final class MacroServiceProvider extends ServiceProvider { public function boot(): void { diff --git a/src/Foundation/Support/PathHelper.php b/src/Foundation/Support/PathHelper.php index a456a07f5..7e1c9bc88 100644 --- a/src/Foundation/Support/PathHelper.php +++ b/src/Foundation/Support/PathHelper.php @@ -8,9 +8,34 @@ { private const CONTAINERS_DIRECTORY_NAME = 'Containers'; - public static function getShipDirectory(): string + + public static function getSharedDirectoryPath(): string + { + return app_path(self::getSharedDirectoryName()); + } + + public static function getAppDirectoryPath(): string { - return app_path('Ship'); + return app_path(); + } + + public static function getAppDirectoryName(): string + { + return 'app'; + } + + public static function getSharedDirectoryName(): string + { + return 'Ship'; + } + + public static function getContainersDirectoryName(): string + { + return 'Containers'; + } + + public static function getSectionDirectoryPath(): string { + return app_path(self::getContainersDirectoryName()); } public static function getShipFolderNames(): array @@ -26,7 +51,7 @@ public static function getShipFolderNames(): array public static function getShipSubDirectories(): array { - return File::directories(self::getShipDirectory()); + return File::directories(self::getSharedDirectoryPath()); } public static function getSectionContainerNames(string $sectionName): array @@ -180,6 +205,6 @@ public static function getContainersSubDirectories(string $subDirectory): array */ public static function getShipSubDirectory(string $subDirectory): string { - return self::getShipDirectory() . DIRECTORY_SEPARATOR . $subDirectory; + return self::getSharedDirectoryPath() . DIRECTORY_SEPARATOR . $subDirectory; } } diff --git a/src/Foundation/Support/Providers/LocalizationServiceProvider.php b/src/Foundation/Support/Providers/LocalizationServiceProvider.php new file mode 100644 index 000000000..31304d81a --- /dev/null +++ b/src/Foundation/Support/Providers/LocalizationServiceProvider.php @@ -0,0 +1,18 @@ +localization(); + foreach ($localization->paths() as $path) { + $this->loadTranslationsFrom($path, $localization->buildNamespaceFor($path)); + $this->loadJsonTranslationsFrom($path); + } + } +} diff --git a/src/Generator/GeneratorsServiceProvider.php b/src/Generator/GeneratorsServiceProvider.php index cab79d4eb..05b1812a3 100644 --- a/src/Generator/GeneratorsServiceProvider.php +++ b/src/Generator/GeneratorsServiceProvider.php @@ -2,7 +2,7 @@ namespace Apiato\Generator; -use Apiato\Abstract\Providers\AggregateServiceProvider; +use Apiato\Abstract\Providers\ServiceProvider; use Apiato\Generator\Commands\ActionGenerator; use Apiato\Generator\Commands\ConfigurationGenerator; use Apiato\Generator\Commands\ContainerApiGenerator; @@ -34,7 +34,7 @@ use Apiato\Generator\Commands\UnitTestGenerator; use Apiato\Generator\Commands\ValueGenerator; -class GeneratorsServiceProvider extends AggregateServiceProvider +class GeneratorsServiceProvider extends ServiceProvider { public function boot(): void { diff --git a/src/Generator/Stubs/providers/generic.stub b/src/Generator/Stubs/providers/generic.stub index b531b0f47..bac66ded6 100644 --- a/src/Generator/Stubs/providers/generic.stub +++ b/src/Generator/Stubs/providers/generic.stub @@ -2,7 +2,7 @@ namespace App\Containers\{{section-name}}\{{container-name}}\Providers; -use Illuminate\Support\ServiceProvider; +use Apiato\Abstract\Providers\ServiceProvider; class {{class-name}} extends ServiceProvider { diff --git a/tests/Functional/Providers/ApiatoServiceProviderTest.php b/tests/Functional/Providers/ApiatoServiceProviderTest.php index 1b23adba7..b80f81313 100644 --- a/tests/Functional/Providers/ApiatoServiceProviderTest.php +++ b/tests/Functional/Providers/ApiatoServiceProviderTest.php @@ -2,6 +2,7 @@ use Apiato\Foundation\Providers\ApiatoServiceProvider; use Apiato\Foundation\Providers\MacroServiceProvider; +use Apiato\Foundation\Support\Providers\LocalizationServiceProvider; use Apiato\Generator\GeneratorsServiceProvider; use Illuminate\Foundation\AliasLoader; use Illuminate\Foundation\Http\Kernel; @@ -25,6 +26,7 @@ $providers = [ GeneratorsServiceProvider::class, MacroServiceProvider::class, + LocalizationServiceProvider::class, // test providers AggregateServiceProvider::class, FirstServiceProvider::class, @@ -84,6 +86,12 @@ expect($this->app->isDeferredService(DeferredServiceProvider::class))->toBeTrue(); })->todo(); + it('can register middlewares in service provider', function (): void { + expect(app(Kernel::class) + ->hasMiddleware(BeforeMiddleware::class)) + ->toBeTrue(); + }); + it('registers Core commands', function (): void { $actual = collect(Artisan::all()); $commands = [ @@ -98,72 +106,4 @@ expect($actual->has($command->value))->toBeTrue(); }); }); - - it('loads helper functions form Ship', function (): void { - expect(function_exists('this_is_a_test_function_to_test_functions_file'))->toBeTrue() - ->and(function_exists('this_is_a_test_function_to_test_helpers_file'))->toBeTrue(); - }); - - it('can register middlewares in the service provider', function (): void { - expect(app(Kernel::class) - ->hasMiddleware(BeforeMiddleware::class)) - ->toBeTrue(); - }); - - describe('can register middlewares via middleware service provider', function (): void { - it('can register middlewares', function (): void { - $middlewares = [ - 'test-middleware', - ]; - - expect($middlewares) - ->each(function (Expectation $middleware) { - expect($this->app->hasMiddleware($middleware->value))->toBeTrue(); - }); - })->todo(); - - it('can register middlewares in groups', function (): void { - $middlewares = [ - 'test-middleware', - ]; - - expect($middlewares) - ->each(function (Expectation $middleware) { - expect($this->app->hasMiddleware($middleware->value))->toBeTrue(); - }); - })->todo(); - - it('can register route middlewares', function (): void { - $middlewares = [ - 'test-middleware', - ]; - - expect($middlewares) - ->each(function (Expectation $middleware) { - expect($this->app->hasMiddleware($middleware->value))->toBeTrue(); - }); - })->todo(); - - it('can add middlewares aliases', function (): void { - $middlewares = [ - 'test-middleware', - ]; - - expect($middlewares) - ->each(function (Expectation $middleware) { - expect($this->app->hasMiddleware($middleware->value))->toBeTrue(); - }); - })->todo(); - - it('can set middleware priority', function (): void { - $middlewares = [ - 'test-middleware', - ]; - - expect($middlewares) - ->each(function (Expectation $middleware) { - expect($this->app->hasMiddleware($middleware->value))->toBeTrue(); - }); - })->todo(); - }); })->covers(ApiatoServiceProvider::class); diff --git a/tests/Functional/Providers/ConfigurationTest.php b/tests/Functional/Providers/ConfigurationTest.php index 0adbb0369..1fec642a4 100644 --- a/tests/Functional/Providers/ConfigurationTest.php +++ b/tests/Functional/Providers/ConfigurationTest.php @@ -1,10 +1,7 @@ has($command->value))->toBeTrue(); }); }); - - it('can list Core middlewares', function (): void { - $middlewares = [ - ValidateJsonContent::class, - ProcessETag::class, - Profiler::class, - ]; - - expect((new ApplicationBuilder())->apiMiddlewares()) - ->toBe($middlewares); - }); })->covers(ApplicationBuilder::class); diff --git a/tests/Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages/en/errors.php b/tests/Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages/en/errors.php new file mode 100644 index 000000000..3f0356486 --- /dev/null +++ b/tests/Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages/en/errors.php @@ -0,0 +1,5 @@ + 'forbidden', +]; diff --git a/tests/Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages/fa/errors.php b/tests/Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages/fa/errors.php new file mode 100644 index 000000000..63bb48986 --- /dev/null +++ b/tests/Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages/fa/errors.php @@ -0,0 +1,5 @@ + 'ممنوع', +]; diff --git a/tests/Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages/fr.json b/tests/Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages/fr.json new file mode 100644 index 000000000..76433ac7c --- /dev/null +++ b/tests/Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages/fr.json @@ -0,0 +1,3 @@ +{ + "forbidden": "interdit" +} diff --git a/tests/Support/Doubles/Fakes/Laravel/app/Ship/Languages/en/errors.php b/tests/Support/Doubles/Fakes/Laravel/app/Ship/Languages/en/errors.php new file mode 100644 index 000000000..3f0356486 --- /dev/null +++ b/tests/Support/Doubles/Fakes/Laravel/app/Ship/Languages/en/errors.php @@ -0,0 +1,5 @@ + 'forbidden', +]; diff --git a/tests/Support/Doubles/Fakes/Laravel/app/Ship/Languages/fa/errors.php b/tests/Support/Doubles/Fakes/Laravel/app/Ship/Languages/fa/errors.php new file mode 100644 index 000000000..63bb48986 --- /dev/null +++ b/tests/Support/Doubles/Fakes/Laravel/app/Ship/Languages/fa/errors.php @@ -0,0 +1,5 @@ + 'ممنوع', +]; diff --git a/tests/Support/Doubles/Fakes/Laravel/app/Ship/Languages/fr.json b/tests/Support/Doubles/Fakes/Laravel/app/Ship/Languages/fr.json new file mode 100644 index 000000000..76433ac7c --- /dev/null +++ b/tests/Support/Doubles/Fakes/Laravel/app/Ship/Languages/fr.json @@ -0,0 +1,3 @@ +{ + "forbidden": "interdit" +} diff --git a/tests/Support/Doubles/Fakes/Laravel/bootstrap/app.php b/tests/Support/Doubles/Fakes/Laravel/bootstrap/app.php index 2699a9613..ba7dbef4a 100644 --- a/tests/Support/Doubles/Fakes/Laravel/bootstrap/app.php +++ b/tests/Support/Doubles/Fakes/Laravel/bootstrap/app.php @@ -1,11 +1,12 @@ create(); return Application::configure(basePath: $basePath) ->withEvents($apiato->events()) diff --git a/tests/Support/Doubles/Fakes/Laravel/composer.json b/tests/Support/Doubles/Fakes/Laravel/composer.json index 0fc2de279..69daaff92 100644 --- a/tests/Support/Doubles/Fakes/Laravel/composer.json +++ b/tests/Support/Doubles/Fakes/Laravel/composer.json @@ -9,10 +9,5 @@ "Tests\\Support\\Doubles\\Fakes\\Laravel\\app\\": "app" } }, - "extra": { - "laravel": { - "dont-discover": [] - } - }, "minimum-stability": "dev" } diff --git a/tests/Unit/Foundation/ApiatoTest.php b/tests/Unit/Foundation/ApiatoTest.php new file mode 100644 index 000000000..50a93c43b --- /dev/null +++ b/tests/Unit/Foundation/ApiatoTest.php @@ -0,0 +1,35 @@ +withTranslations(function (Localization $localization): void { + $localization->buildNamespaceUsing(fn (string $path): string => 'test'); + }) + ->create(); + + app()->register(LocalizationServiceProvider::class, true); + + $this->app->setLocale('fa'); + expect(__('test::errors.forbidden'))->toBe('ممنوع'); + }); + + it('can list Core middlewares', function (): void { + $middlewares = [ + ValidateJsonContent::class, + ProcessETag::class, + Profiler::class, + ]; + + expect(Apiato::instance()->apiMiddlewares()) + ->toBe($middlewares); + }); +})->covers(Apiato::class); diff --git a/tests/Unit/Foundation/Configuration/LocalizationTest.php b/tests/Unit/Foundation/Configuration/LocalizationTest.php new file mode 100644 index 000000000..b5dcf4a74 --- /dev/null +++ b/tests/Unit/Foundation/Configuration/LocalizationTest.php @@ -0,0 +1,38 @@ +buildNamespaceFor( + PathHelper::getSharedDirectoryPath() . '/Languages', + ); + + expect($namespace)->toBe('ship'); + + $namespace = $localization->buildNamespaceFor( + __DIR__ . '/../../../Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages', + ); + + expect($namespace)->toBe('mySection@book'); + }); + }); + + it('can set translation paths', function (): void { + $localization = new Localization(); + + $localization->loadTranslationsFrom( + __DIR__ . '/../../../Support/Doubles/Fakes/Laravel/app/Ship/Languages', + __DIR__ . '/../../../Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages', + ); + + expect($localization->paths())->toBe([ + __DIR__ . '/../../../Support/Doubles/Fakes/Laravel/app/Ship/Languages', + __DIR__ . '/../../../Support/Doubles/Fakes/Laravel/app/Containers/MySection/Book/Languages', + ]); + }); +})->covers(Localization::class); diff --git a/tests/Unit/Foundation/Loaders/HelperLoaderTest.php b/tests/Unit/Foundation/Loaders/HelperLoaderTest.php new file mode 100644 index 000000000..6c7eb1ed8 --- /dev/null +++ b/tests/Unit/Foundation/Loaders/HelperLoaderTest.php @@ -0,0 +1,13 @@ +load(); + + expect(function_exists('this_is_a_test_function_to_test_functions_file'))->toBeTrue() + ->and(function_exists('this_is_a_test_function_to_test_helpers_file'))->toBeTrue(); + }); +})->covers(HelperLoader::class); diff --git a/tests/Unit/Foundation/Support/Providers/MacroServiceProviderTest.php b/tests/Unit/Foundation/Providers/MacroServiceProviderTest.php similarity index 100% rename from tests/Unit/Foundation/Support/Providers/MacroServiceProviderTest.php rename to tests/Unit/Foundation/Providers/MacroServiceProviderTest.php diff --git a/tests/Unit/Foundation/Support/PathHelperTest.php b/tests/Unit/Foundation/Support/PathHelperTest.php index 1bd847a8e..380a521e0 100644 --- a/tests/Unit/Foundation/Support/PathHelperTest.php +++ b/tests/Unit/Foundation/Support/PathHelperTest.php @@ -14,7 +14,7 @@ class PathHelperTest extends UnitTestCase public function testGetShipFoldersNamesReturnsCorrectNames(): void { File::shouldReceive('directories') - ->with(PathHelper::getShipDirectory()) + ->with(PathHelper::getSharedDirectoryPath()) ->andReturn(['/path/to/ship1', '/path/to/ship2']); $result = PathHelper::getShipFolderNames(); diff --git a/tests/Unit/Foundation/Support/Providers/LocalizationServiceProviderTest.php b/tests/Unit/Foundation/Support/Providers/LocalizationServiceProviderTest.php new file mode 100644 index 000000000..5eb4bdad9 --- /dev/null +++ b/tests/Unit/Foundation/Support/Providers/LocalizationServiceProviderTest.php @@ -0,0 +1,30 @@ +localization(); + $this->app->setLocale('en'); + foreach ($localization->paths() as $path) { + expect(__($localization->buildNamespaceFor($path) . '::errors.forbidden'))->toBe('forbidden'); + } + + $this->app->setLocale('fa'); + foreach ($localization->paths() as $path) { + expect(__($localization->buildNamespaceFor($path) . '::errors.forbidden'))->toBe('ممنوع'); + } + }); + + + it('loads json translation files', function (): void { + $localization = Apiato::instance()->localization(); + + $this->app->setLocale('fr'); + + expect($localization->paths())->each(function () { + expect(__('forbidden'))->toBe('interdit'); + }); + }); +})->covers(LocalizationServiceProvider::class);