fix: DockerSecretsResolver - don't normalize absolute paths like /var/www/html/...
Some checks failed
Deploy Application / deploy (push) Has been cancelled
Some checks failed
Deploy Application / deploy (push) Has been cancelled
This commit is contained in:
@@ -2,18 +2,144 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Framework\Admin\AdminApiHandler;
|
||||
use App\Framework\Admin\AdminPageRenderer;
|
||||
use App\Framework\Admin\Factories\AdminFormFactory;
|
||||
use App\Framework\Admin\Factories\AdminTableFactory;
|
||||
use App\Framework\Admin\Factories\RepositoryAdapterFactory;
|
||||
use App\Framework\Admin\Services\CrudService;
|
||||
use App\Framework\Admin\ValueObjects\CrudConfig;
|
||||
use App\Framework\Http\HttpRequest;
|
||||
use App\Framework\Core\PathProvider;
|
||||
use App\Framework\DI\DefaultContainer;
|
||||
use App\Framework\Discovery\Results\AttributeRegistry;
|
||||
use App\Framework\Discovery\Results\DiscoveryRegistry;
|
||||
use App\Framework\Discovery\Results\InterfaceRegistry;
|
||||
use App\Framework\Discovery\Results\TemplateRegistry;
|
||||
use App\Framework\Http\Request;
|
||||
use App\Framework\Http\Responses\Redirect;
|
||||
use App\Framework\Http\Responses\ViewResult;
|
||||
use App\Framework\View\TemplateRenderer;
|
||||
use App\Framework\LiveComponents\ComponentCacheManager;
|
||||
use App\Framework\LiveComponents\ComponentMetadataCache;
|
||||
use App\Framework\LiveComponents\ComponentRegistry;
|
||||
use App\Framework\LiveComponents\LiveComponentHandler;
|
||||
use App\Framework\LiveComponents\Performance\NestedPerformanceTracker;
|
||||
use App\Framework\Router\Result\ViewResult;
|
||||
use App\Framework\View\Dom\Renderer\HtmlRenderer;
|
||||
use App\Framework\View\LiveComponentRenderer;
|
||||
use App\Framework\View\Loading\TemplateLoader;
|
||||
use App\Framework\View\Table\Table;
|
||||
use App\Framework\View\TemplateProcessor;
|
||||
use App\Framework\Cache\Driver\NullCache;
|
||||
use App\Framework\Cache\GeneralCache;
|
||||
use App\Framework\Serializer\Serializer;
|
||||
use App\Framework\DateTime\SystemClock;
|
||||
use App\Framework\Http\Session\Session;
|
||||
use App\Framework\Http\Session\SessionId;
|
||||
use App\Framework\Random\SecureRandomGenerator;
|
||||
use App\Framework\Security\CsrfTokenGenerator;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->renderer = Mockery::mock(TemplateRenderer::class);
|
||||
// Create minimal real instances for final classes
|
||||
// Since many classes are final, we create real instances with minimal dependencies
|
||||
$container = new DefaultContainer();
|
||||
|
||||
// Create DiscoveryRegistry
|
||||
$discoveryRegistry = new DiscoveryRegistry(
|
||||
attributes: new AttributeRegistry(),
|
||||
interfaces: new InterfaceRegistry([]),
|
||||
templates: new TemplateRegistry([])
|
||||
);
|
||||
|
||||
// Create TemplateLoader for LiveComponentRenderer
|
||||
$pathProvider = new PathProvider(__DIR__ . '/../../../../');
|
||||
$nullCacheDriver = new NullCache();
|
||||
$serializer = Mockery::mock(Serializer::class);
|
||||
$serializer->shouldReceive('serialize')->andReturnUsing(fn($data) => serialize($data));
|
||||
$serializer->shouldReceive('unserialize')->andReturnUsing(fn($data) => unserialize($data));
|
||||
$cache = new GeneralCache($nullCacheDriver, $serializer);
|
||||
$templateLoader = new TemplateLoader(
|
||||
pathProvider: $pathProvider,
|
||||
cache: $cache,
|
||||
discoveryRegistry: null,
|
||||
templates: [],
|
||||
templatePath: '/src/Framework/View/templates',
|
||||
cacheEnabled: false
|
||||
);
|
||||
|
||||
// Create TemplateProcessor
|
||||
$templateProcessor = new TemplateProcessor(
|
||||
astTransformers: [],
|
||||
stringProcessors: [],
|
||||
container: $container,
|
||||
chainOptimizer: null,
|
||||
compiledTemplateCache: null,
|
||||
performanceTracker: null
|
||||
);
|
||||
|
||||
// Create real Session instance
|
||||
$session = Session::fromArray(
|
||||
SessionId::fromString(str_repeat('a', 32)),
|
||||
new SystemClock(),
|
||||
new CsrfTokenGenerator(new SecureRandomGenerator()),
|
||||
[]
|
||||
);
|
||||
|
||||
// Create LiveComponentRenderer
|
||||
$liveComponentRenderer = new LiveComponentRenderer(
|
||||
templateLoader: $templateLoader,
|
||||
templateProcessor: $templateProcessor,
|
||||
session: $session
|
||||
);
|
||||
|
||||
// Create real instances for final classes with minimal dependencies
|
||||
$cacheKeyBuilder = new \App\Framework\LiveComponents\Caching\CacheKeyBuilder();
|
||||
$cacheManager = new ComponentCacheManager(
|
||||
cache: $cache,
|
||||
cacheKeyBuilder: $cacheKeyBuilder
|
||||
);
|
||||
|
||||
$eventDispatcher = new \App\Framework\LiveComponents\ComponentEventDispatcher();
|
||||
$handler = new LiveComponentHandler(
|
||||
eventDispatcher: $eventDispatcher,
|
||||
session: $session
|
||||
);
|
||||
|
||||
$metadataCompiler = new \App\Framework\LiveComponents\Performance\ComponentMetadataCompiler();
|
||||
$metadataCache = new ComponentMetadataCache(
|
||||
cache: $cache,
|
||||
compiler: $metadataCompiler
|
||||
);
|
||||
|
||||
$highResClock = new \App\Framework\DateTime\HighResolutionClock();
|
||||
$memoryMonitor = new \App\Framework\Performance\MemoryMonitor();
|
||||
$performanceTracker = new NestedPerformanceTracker(
|
||||
clock: new SystemClock(),
|
||||
highResClock: $highResClock,
|
||||
memoryMonitor: $memoryMonitor
|
||||
);
|
||||
|
||||
// Create real ComponentRegistry
|
||||
$componentRegistry = new ComponentRegistry(
|
||||
container: $container,
|
||||
discoveryRegistry: $discoveryRegistry,
|
||||
renderer: $liveComponentRenderer,
|
||||
cacheManager: $cacheManager,
|
||||
handler: $handler,
|
||||
metadataCache: $metadataCache,
|
||||
performanceTracker: $performanceTracker
|
||||
);
|
||||
|
||||
$this->pageRenderer = new AdminPageRenderer($componentRegistry);
|
||||
$this->formFactory = Mockery::mock(AdminFormFactory::class);
|
||||
$this->service = new CrudService($this->renderer, $this->formFactory);
|
||||
$this->tableFactory = Mockery::mock(AdminTableFactory::class);
|
||||
$apiHandler = new AdminApiHandler();
|
||||
$adapterFactory = new RepositoryAdapterFactory();
|
||||
$this->service = new CrudService(
|
||||
$this->pageRenderer,
|
||||
$this->formFactory,
|
||||
$this->tableFactory,
|
||||
$apiHandler,
|
||||
$adapterFactory
|
||||
);
|
||||
|
||||
$this->config = CrudConfig::forResource(
|
||||
resource: 'campaigns',
|
||||
@@ -31,41 +157,54 @@ afterEach(function () {
|
||||
|
||||
describe('CrudService', function () {
|
||||
describe('renderIndex', function () {
|
||||
it('renders index view with items and pagination', function () {
|
||||
it('renders index view with items using AdminPageRenderer', function () {
|
||||
$items = [
|
||||
['id' => '1', 'name' => 'Campaign 1', 'status' => 'active'],
|
||||
['id' => '2', 'name' => 'Campaign 2', 'status' => 'draft'],
|
||||
];
|
||||
|
||||
$pagination = [
|
||||
'current_page' => 1,
|
||||
'total_pages' => 5,
|
||||
'per_page' => 10,
|
||||
];
|
||||
|
||||
$request = Mockery::mock(HttpRequest::class);
|
||||
$request = Mockery::mock(Request::class);
|
||||
$request->shouldReceive('uri')->andReturn('/admin/campaigns');
|
||||
|
||||
$mockTable = Mockery::mock(Table::class);
|
||||
$mockTable->shouldReceive('render')->andReturn('<table>...</table>');
|
||||
|
||||
$this->tableFactory->shouldReceive('create')
|
||||
->once()
|
||||
->andReturn($mockTable);
|
||||
|
||||
$result = $this->service->renderIndex(
|
||||
$this->config,
|
||||
$items,
|
||||
$request,
|
||||
$pagination
|
||||
$request
|
||||
);
|
||||
|
||||
expect($result)->toBeInstanceOf(ViewResult::class);
|
||||
expect($result->template)->toBe('crud-index');
|
||||
expect($result->data['items'])->toBe($items);
|
||||
expect($result->data['pagination'])->toBe($pagination);
|
||||
expect($result->data['resource'])->toBe('campaigns');
|
||||
expect($result->data['createUrl'])->toBe('/admin/campaigns/create');
|
||||
expect($result->template)->toBe('admin-index');
|
||||
});
|
||||
|
||||
it('includes create action when canCreate is true', function () {
|
||||
$items = [];
|
||||
$request = Mockery::mock(Request::class);
|
||||
$request->shouldReceive('uri')->andReturn('/admin/campaigns');
|
||||
|
||||
$mockTable = Mockery::mock(Table::class);
|
||||
$mockTable->shouldReceive('render')->andReturn('');
|
||||
|
||||
$this->tableFactory->shouldReceive('create')->andReturn($mockTable);
|
||||
|
||||
$result = $this->service->renderIndex($this->config, $items, $request);
|
||||
|
||||
expect($result)->toBeInstanceOf(ViewResult::class);
|
||||
expect($result->data['actions'])->toBeArray();
|
||||
expect($result->data['actions'][0]['label'])->toBe('Create Campaign');
|
||||
});
|
||||
});
|
||||
|
||||
describe('renderCreate', function () {
|
||||
it('renders create form with default configuration', function () {
|
||||
it('renders create form using AdminPageRenderer', function () {
|
||||
$formFields = [
|
||||
['type' => 'text', 'name' => 'name', 'label' => 'Name'],
|
||||
'name' => ['type' => 'text', 'label' => 'Name'],
|
||||
];
|
||||
|
||||
$mockForm = Mockery::mock();
|
||||
@@ -82,13 +221,11 @@ describe('CrudService', function () {
|
||||
);
|
||||
|
||||
expect($result)->toBeInstanceOf(ViewResult::class);
|
||||
expect($result->template)->toBe('crud-create');
|
||||
expect($result->template)->toBe('admin-form');
|
||||
expect($result->data['title'])->toBe('Create Campaign');
|
||||
expect($result->data['formId'])->toBe('campaign-form');
|
||||
expect($result->data['backUrl'])->toBe('/admin/campaigns');
|
||||
});
|
||||
|
||||
it('renders create form with help text', function () {
|
||||
it('renders create form with help text as subtitle', function () {
|
||||
$formFields = [];
|
||||
$helpText = 'Fill in the campaign details carefully.';
|
||||
|
||||
@@ -105,14 +242,15 @@ describe('CrudService', function () {
|
||||
$helpText
|
||||
);
|
||||
|
||||
expect($result->data['helpText'])->toBe($helpText);
|
||||
expect($result)->toBeInstanceOf(ViewResult::class);
|
||||
expect($result->data['subtitle'])->toBe($helpText);
|
||||
});
|
||||
});
|
||||
|
||||
describe('renderEdit', function () {
|
||||
it('renders edit form with item data and metadata', function () {
|
||||
it('renders edit form using AdminPageRenderer', function () {
|
||||
$formFields = [
|
||||
['type' => 'text', 'name' => 'name', 'label' => 'Name'],
|
||||
'name' => ['type' => 'text', 'label' => 'Name'],
|
||||
];
|
||||
|
||||
$itemData = [
|
||||
@@ -144,15 +282,13 @@ describe('CrudService', function () {
|
||||
);
|
||||
|
||||
expect($result)->toBeInstanceOf(ViewResult::class);
|
||||
expect($result->template)->toBe('crud-edit');
|
||||
expect($result->template)->toBe('admin-form');
|
||||
expect($result->data['title'])->toBe('Edit Campaign');
|
||||
expect($result->data['metadata'])->toBe($metadata);
|
||||
expect($result->data['deleteUrl'])->toBe('/admin/campaigns/delete/123');
|
||||
});
|
||||
});
|
||||
|
||||
describe('renderShow', function () {
|
||||
it('renders show view with fields and metadata', function () {
|
||||
it('renders show view using AdminPageRenderer', function () {
|
||||
$fields = [
|
||||
['label' => 'Name', 'value' => 'Test Campaign', 'type' => 'text'],
|
||||
['label' => 'Status', 'value' => 'Active', 'type' => 'badge', 'color' => 'success'],
|
||||
@@ -171,7 +307,7 @@ describe('CrudService', function () {
|
||||
);
|
||||
|
||||
expect($result)->toBeInstanceOf(ViewResult::class);
|
||||
expect($result->template)->toBe('crud-show');
|
||||
expect($result->template)->toBe('admin-show');
|
||||
expect($result->data['fields'])->toBe($fields);
|
||||
expect($result->data['metadata'])->toBe($metadata);
|
||||
expect($result->data['editUrl'])->toBe('/admin/campaigns/edit/123');
|
||||
@@ -180,7 +316,7 @@ describe('CrudService', function () {
|
||||
|
||||
describe('redirectAfterCreate', function () {
|
||||
it('redirects to index after successful create', function () {
|
||||
$request = Mockery::mock(HttpRequest::class);
|
||||
$request = Mockery::mock(Request::class);
|
||||
$request->parsedBody = Mockery::mock();
|
||||
$request->parsedBody->shouldReceive('get')
|
||||
->with('action')
|
||||
@@ -197,7 +333,7 @@ describe('CrudService', function () {
|
||||
});
|
||||
|
||||
it('redirects to create form when save-and-continue is requested', function () {
|
||||
$request = Mockery::mock(HttpRequest::class);
|
||||
$request = Mockery::mock(Request::class);
|
||||
$request->parsedBody = Mockery::mock();
|
||||
$request->parsedBody->shouldReceive('get')
|
||||
->with('action')
|
||||
@@ -215,7 +351,7 @@ describe('CrudService', function () {
|
||||
|
||||
describe('redirectAfterUpdate', function () {
|
||||
it('redirects to index after successful update', function () {
|
||||
$request = Mockery::mock(HttpRequest::class);
|
||||
$request = Mockery::mock(Request::class);
|
||||
$request->parsedBody = Mockery::mock();
|
||||
$request->parsedBody->shouldReceive('get')
|
||||
->with('action')
|
||||
@@ -231,7 +367,7 @@ describe('CrudService', function () {
|
||||
});
|
||||
|
||||
it('redirects to show view when save-and-view is requested', function () {
|
||||
$request = Mockery::mock(HttpRequest::class);
|
||||
$request = Mockery::mock(Request::class);
|
||||
$request->parsedBody = Mockery::mock();
|
||||
$request->parsedBody->shouldReceive('get')
|
||||
->with('action')
|
||||
|
||||
Reference in New Issue
Block a user