diff --git a/.github/workflows/cs-tests.yml b/.github/workflows/cs-tests.yml
new file mode 100644
index 0000000..3da9965
--- /dev/null
+++ b/.github/workflows/cs-tests.yml
@@ -0,0 +1,46 @@
+on:
+ - push
+
+name: Run phpcs checks
+
+jobs:
+ mutation:
+ name: PHP ${{ matrix.php }}-${{ matrix.os }}
+
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ matrix:
+ os:
+ - ubuntu-latest
+
+ php:
+ - "8.1"
+ - "8.2"
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Install PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "${{ matrix.php }}"
+ tools: composer:v2, cs2pr
+ coverage: none
+
+ - name: Determine composer cache directory
+ run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV
+
+ - name: Cache dependencies installed with composer
+ uses: actions/cache@v3
+ with:
+ path: ${{ env.COMPOSER_CACHE_DIR }}
+ key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }}
+ restore-keys: |
+ php${{ matrix.php }}-composer-
+ - name: Install dependencies with composer
+ run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
+
+ - name: Run phpcs checks
+ run: vendor/bin/phpcs
diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
new file mode 100644
index 0000000..377bcfb
--- /dev/null
+++ b/.github/workflows/static-analysis.yml
@@ -0,0 +1,46 @@
+on:
+ - push
+
+name: Run static analysis
+
+jobs:
+ mutation:
+ name: PHP ${{ matrix.php }}-${{ matrix.os }}
+
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ matrix:
+ os:
+ - ubuntu-latest
+
+ php:
+ - "8.1"
+ - "8.2"
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Install PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "${{ matrix.php }}"
+ tools: composer:v2, cs2pr
+ coverage: none
+
+ - name: Determine composer cache directory
+ run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV
+
+ - name: Cache dependencies installed with composer
+ uses: actions/cache@v3
+ with:
+ path: ${{ env.COMPOSER_CACHE_DIR }}
+ key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }}
+ restore-keys: |
+ php${{ matrix.php }}-composer-
+ - name: Install dependencies with composer
+ run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
+
+ - name: Run static analysis
+ run: vendor/bin/psalm --no-cache --output-format=github --show-info=false --threads=4
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
new file mode 100644
index 0000000..593bed9
--- /dev/null
+++ b/.github/workflows/unit-tests.yml
@@ -0,0 +1,46 @@
+on:
+ - push
+
+name: Run PHPUnit tests
+
+jobs:
+ mutation:
+ name: PHP ${{ matrix.php }}-${{ matrix.os }}
+
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ matrix:
+ os:
+ - ubuntu-latest
+
+ php:
+ - "8.1"
+ - "8.2"
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Install PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "${{ matrix.php }}"
+ tools: composer:v2, cs2pr
+ coverage: none
+
+ - name: Determine composer cache directory
+ run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV
+
+ - name: Cache dependencies installed with composer
+ uses: actions/cache@v3
+ with:
+ path: ${{ env.COMPOSER_CACHE_DIR }}
+ key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }}
+ restore-keys: |
+ php${{ matrix.php }}-composer-
+ - name: Install dependencies with composer
+ run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
+
+ - name: Run PHPUnit tests
+ run: vendor/bin/phpunit --colors=always
diff --git a/.gitignore b/.gitignore
index f3e6777..2f9a784 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,3 +33,5 @@ com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
+.phpcs-cache
+.phpunit.result.cache
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 774151f..8701d82 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,21 @@
+## 4.2.0 - 2023-08-14
+
+### Changed
+* Added unit tests & removed laminas/laminas-log dependency
+
+### Added
+* Unit Tests
+
+### Deprecated
+* Nothing
+
+### Removed
+* laminas/laminas-log dependency
+
+### Fixed
+* Decoupled packages from laminas/laminas-log
+
+
## 4.0.1 - 2022-05-31
### Changed
diff --git a/LICENSE.md b/LICENSE.md
index 24e7185..6757d85 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2020 Apidemia
+Copyright (c) 2023 Apidemia
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/OSSMETADATA b/OSSMETADATA
index b96d4a4..58d43b8 100644
--- a/OSSMETADATA
+++ b/OSSMETADATA
@@ -1 +1 @@
-osslifecycle=active
+osslifecycle=maintained
diff --git a/README.md b/README.md
index a782176..34e893b 100644
--- a/README.md
+++ b/README.md
@@ -3,13 +3,13 @@
DotKernel form component extending and customizing [laminas-form](https://github.com/laminas/laminas-form)

-
-
-
-
+
[](https://github.com/dotkernel/dot-form/issues)
[](https://github.com/dotkernel/dot-form/network)
[](https://github.com/dotkernel/dot-form/stargazers)
[](https://github.com/dotkernel/dot-form/blob/4.0/LICENSE.md)
+[](https://github.com/dotkernel/dot-form/actions/workflows/static-analysis.yml)
+
+[](https://insight.symfony.com/projects/370a5200-2e49-47da-9988-8e1de8f49502)
diff --git a/composer.json b/composer.json
index a100d06..e4d2e33 100644
--- a/composer.json
+++ b/composer.json
@@ -18,24 +18,40 @@
}
],
"require": {
- "php": "~7.4.0 || ~8.0.0 || ~8.1.0",
+ "php": "~8.1 || ~8.2",
"laminas/laminas-servicemanager": "^3.10",
- "laminas/laminas-form": "^3.1.1",
- "laminas/laminas-log": "2.15.2"
+ "laminas/laminas-form": "^3.0"
},
"require-dev": {
- "phpunit/phpunit": "^9.1",
- "squizlabs/php_codesniffer": "^3.5",
- "doctrine/annotations": "^1.10"
+ "phpunit/phpunit": "^10.2",
+ "laminas/laminas-coding-standard": "^2.5",
+ "vimeo/psalm": "^5.13"
},
"autoload": {
"psr-4": {
- "Dot\\Form\\": "src"
+ "Dot\\Form\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
- "DotTest\\Form\\": "tests"
+ "DotTest\\Form\\": "test/"
}
+ },
+ "config": {
+ "sort-packages": true,
+ "allow-plugins": {
+ "dealerdirect/phpcodesniffer-composer-installer": true
+ }
+ },
+ "scripts": {
+ "check": [
+ "@cs-check",
+ "@test"
+ ],
+ "cs-check": "phpcs",
+ "cs-fix": "phpcbf",
+ "test": "phpunit --colors=always",
+ "test-coverage": "phpunit --colors=always --coverage-clover clover.xml",
+ "static-analysis": "psalm --shepherd --stats"
}
}
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 0000000..1efe663
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ src
+ test
+
+
+
+
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..75be41e
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ ./test
+
+
+
+
+
+ ./src
+
+
+
diff --git a/psalm.xml b/psalm.xml
new file mode 100644
index 0000000..2015b2a
--- /dev/null
+++ b/psalm.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php
index 99d7daf..c3e6c25 100644
--- a/src/ConfigProvider.php
+++ b/src/ConfigProvider.php
@@ -1,23 +1,13 @@
$this->getDependenciesConfig(),
'view_helpers' => $this->getViewHelpersConfig(),
-
- 'dot_form' => [
+ 'dot_form' => [
'forms' => [],
-
],
];
}
@@ -39,21 +27,18 @@ public function getDependenciesConfig(): array
'abstract_factories' => [
FormAbstractServiceFactory::class,
],
- 'aliases' => [
- 'Laminas\Form\Annotation\FormAnnotationBuilder' => 'FormAnnotationBuilder',
- AnnotationBuilder::class => 'FormAnnotationBuilder',
+ 'aliases' => [
FormElementManager::class => 'FormElementManager',
],
- 'factories' => [
+ 'factories' => [
'FormElementManager' => FormElementManagerFactory::class,
- 'FormAnnotationBuilder' => AnnotationBuilderFactory::class,
- ]
+ ],
];
}
public function getViewHelpersConfig(): array
{
- $laminasFormConfigProvider = new \Laminas\Form\ConfigProvider();
+ $laminasFormConfigProvider = new LaminasConfigProvider();
return $laminasFormConfigProvider->getViewHelperConfig();
}
}
diff --git a/src/Factory/FormAbstractServiceFactory.php b/src/Factory/FormAbstractServiceFactory.php
index 80cb9db..6d787bc 100644
--- a/src/Factory/FormAbstractServiceFactory.php
+++ b/src/Factory/FormAbstractServiceFactory.php
@@ -1,94 +1,107 @@
getConfig($container);
+ if (empty($config)) {
+ return false;
+ }
+
+ return ! empty($config[$requestedName]) && is_array($config[$requestedName]);
}
/**
- * @param ContainerInterface $container
* @param string $requestedName
- * @param array|null $options
- * @return \Laminas\Form\ElementInterface
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
*/
- public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
+ public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null): FormInterface
{
- $parts = explode('.', $requestedName);
-
- //merge configs if extends another form
- $config = $this->getConfig($container);
- $specificConfig = $config[$parts[1]];
+ $config = $this->getConfig($container);
+ $config = $config[$requestedName];
+ $factory = $this->getFormFactory($container);
- do {
- $extendsConfigKey = isset($specificConfig['extends']) && is_string($specificConfig['extends'])
- ? trim($specificConfig['extends'])
- : null;
-
- unset($specificConfig['extends']);
-
- if (!is_null($extendsConfigKey)
- && array_key_exists($extendsConfigKey, $config)
- && is_array($config[$extendsConfigKey])
- ) {
- $specificConfig = ArrayUtils::merge($config[$extendsConfigKey], $specificConfig);
- }
- } while ($extendsConfigKey != null);
-
- $this->config[$parts[1]] = $specificConfig;
-
- return parent::__invoke($container, $parts[1], $options);
+ $this->marshalInputFilter($config, $container, $factory);
+ return $factory->createForm($config);
}
/**
- * @param ContainerInterface $container
- * @return array
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
*/
protected function getConfig(ContainerInterface $container): array
{
- parent::getConfig($container);
- if (!empty($this->config)) {
+ if ($this->config !== null) {
+ return $this->config;
+ }
+
+ if (! $container->has('config')) {
+ $this->config = [];
+ return $this->config;
+ }
+
+ $config = $container->get('config');
+ if (! isset($config[$this->configKey]) || ! is_array($config[$this->configKey])) {
+ $this->config = [];
+ return $this->config;
+ }
+
+ $this->config = $config[$this->configKey];
+
+ if (! empty($this->config)) {
if (isset($this->config[$this->subConfigKey]) && is_array($this->config[$this->subConfigKey])) {
$this->config = $this->config[$this->subConfigKey];
}
@@ -97,28 +110,30 @@ protected function getConfig(ContainerInterface $container): array
return $this->config;
}
- protected function getFormFactory(ContainerInterface $container): \Laminas\Form\Factory
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ protected function getFormFactory(ContainerInterface $container): FormFactory
{
- $formFactory = parent::getFormFactory($container);
- if ($container->has('InputFilterManager')) {
- $formFactory->setInputFilterFactory(new Factory($container->get('InputFilterManager')));
+ if ($this->factory instanceof Factory) {
+ return $this->factory;
+ }
+
+ $elements = null;
+ if ($container->has(FormElementManager::class)) {
+ $elements = $container->get(FormElementManager::class);
}
- return $formFactory;
+ $this->factory = new Factory($elements);
+ return $this->factory;
}
/**
- * Marshal the input filter into the configuration
- *
- * If an input filter is specified:
- * - if the InputFilterManager is present, checks if it's there; if so,
- * retrieves it and resets the specification to the instance.
- * - otherwise, pulls the input filter factory from the form factory, and
- * attaches the FilterManager and ValidatorManager to it.
- *
- * @param array $config
+ * @throws NotFoundExceptionInterface
+ * @throws ContainerExceptionInterface
*/
- protected function marshalInputFilter(array &$config, ContainerInterface $container, \Laminas\Form\Factory $formFactory): void
+ protected function marshalInputFilter(array &$config, ContainerInterface $container, FormFactory $formFactory): void
{
if (! isset($config['input_filter'])) {
return;
@@ -128,11 +143,8 @@ protected function marshalInputFilter(array &$config, ContainerInterface $contai
return;
}
- if (
- is_string($config['input_filter'])
- && $container->has('InputFilterManager')
- ) {
- $inputFilters = $container->get('InputFilterManager');
+ if (is_string($config['input_filter']) && $container->has(InputFilterPluginManager::class)) {
+ $inputFilters = $container->get(InputFilterPluginManager::class);
if ($inputFilters->has($config['input_filter'])) {
$config['input_filter'] = $inputFilters->get($config['input_filter']);
return;
@@ -140,7 +152,14 @@ protected function marshalInputFilter(array &$config, ContainerInterface $contai
}
$inputFilterFactory = $formFactory->getInputFilterFactory();
- $inputFilterFactory->getDefaultFilterChain()->setPluginManager($container->get('FilterManager'));
- $inputFilterFactory->getDefaultValidatorChain()->setPluginManager($container->get('ValidatorManager'));
+ $filterChain = $inputFilterFactory->getDefaultFilterChain();
+ $filterChain?->setPluginManager(
+ $container->get(FilterPluginManager::class)
+ );
+
+ $validatorChain = $inputFilterFactory->getDefaultValidatorChain();
+ $validatorChain?->setPluginManager(
+ $container->get(ValidatorPluginManager::class)
+ );
}
}
diff --git a/src/Factory/FormElementManagerFactory.php b/src/Factory/FormElementManagerFactory.php
index eac5cd2..d9687c3 100644
--- a/src/Factory/FormElementManagerFactory.php
+++ b/src/Factory/FormElementManagerFactory.php
@@ -1,24 +1,21 @@
get('config')['dot_form']['form_manager']);
}
diff --git a/src/FormElementManager.php b/src/FormElementManager.php
index 2ff850e..0ee7e86 100644
--- a/src/FormElementManager.php
+++ b/src/FormElementManager.php
@@ -1,19 +1,14 @@
config = (new ConfigProvider())();
+ }
+
+ public function testHasDependencies(): void
+ {
+ $this->assertArrayHasKey('dependencies', $this->config);
+ }
+
+ public function testDependenciesHasAbstractFactories(): void
+ {
+ $this->assertArrayHasKey('abstract_factories', $this->config['dependencies']);
+ $this->assertContains(
+ FormAbstractServiceFactory::class,
+ $this->config['dependencies']['abstract_factories']
+ );
+ }
+
+ public function testDependenciesHasAliases(): void
+ {
+ $this->assertArrayHasKey('aliases', $this->config['dependencies']);
+ $this->assertArrayHasKey(FormElementManager::class, $this->config['dependencies']['aliases']);
+ }
+
+ public function testDependenciesHasFactories(): void
+ {
+ $this->assertArrayHasKey('factories', $this->config['dependencies']);
+ $this->assertArrayHasKey('FormElementManager', $this->config['dependencies']['factories']);
+ }
+}
diff --git a/test/Factory/FormAbstractServiceFactoryTest.php b/test/Factory/FormAbstractServiceFactoryTest.php
new file mode 100644
index 0000000..927a0ff
--- /dev/null
+++ b/test/Factory/FormAbstractServiceFactoryTest.php
@@ -0,0 +1,256 @@
+subject = new FormAbstractServiceFactory();
+ $this->container = $this->createMock(ContainerInterface::class);
+ }
+
+ public function testClassImplementsAbstractFactoryInterface(): void
+ {
+ $this->assertInstanceOf(AbstractFactoryInterface::class, $this->subject);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ public function testCanCreateReturnsFalseInvalidFormName(): void
+ {
+ $requestedName = 'invalidName';
+
+ $canCreate = $this->subject->canCreate($this->container, $requestedName);
+ $this->assertFalse($canCreate);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ public function testCanCreateReturnsFalseMissingPrefix(): void
+ {
+ $requestedName = 'dot.form';
+
+ $canCreate = $this->subject->canCreate($this->container, $requestedName);
+ $this->assertFalse($canCreate);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ public function testCanCreateReturnsFalseConfigProvided(): void
+ {
+ $requestedName = 'config';
+
+ $canCreate = $this->subject->canCreate($this->container, $requestedName);
+ $this->assertFalse($canCreate);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ * @throws Exception
+ */
+ public function testCanCreateReturnsFalseEmptyConfig(): void
+ {
+ $requestedName = 'dot-form.form';
+ $container = $this->createMock(ContainerInterface::class);
+
+ $container->method('get')->willReturn([]);
+
+ $canCreate = $this->subject->canCreate($container, $requestedName);
+ $this->assertFalse($canCreate);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ * @throws Exception
+ */
+ public function testCanCreateReturnsFalseInvalidConfig(): void
+ {
+ $requestedName = 'dot-form.form';
+ $container = $this->createMock(ContainerInterface::class);
+
+ $container->expects($this->once())->method('has')->willReturn(true);
+ $container->method('get')->willReturn(['dot_form' => []]);
+
+ $canCreate = $this->subject->canCreate($container, $requestedName);
+ $this->assertFalse($canCreate);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ * @throws Exception
+ */
+ public function testCanCreateReturnsTrue(): void
+ {
+ $requestedName = 'dot-form.form';
+ $container = $this->createMock(ContainerInterface::class);
+
+ $container->method('has')->willReturn(true);
+ $container->method('get')->willReturn(['dot_form' => ['dot-form.form' => ['form_name']]]);
+
+ $canCreate = $this->subject->canCreate($container, $requestedName);
+ $this->assertTrue($canCreate);
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetExistingConfig(): void
+ {
+ $config = ['form.dot_forms'];
+ $reflectionClass = new ReflectionClass(FormAbstractServiceFactory::class);
+ $reflectionClass->getProperty('config')->setValue($this->subject, $config);
+
+ $result = $reflectionClass
+ ->getMethod('getConfig')
+ ->invoke($this->subject, $this->container);
+
+ $this->assertSame($config, $result);
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testConfigNotFound(): void
+ {
+ $this->container->expects($this->once())->method('has')->willReturn(false);
+
+ $config = $this->callMethod($this->subject, 'getConfig', $this->container);
+
+ $this->assertSame([], $config);
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetInvalidConfig(): void
+ {
+ $this->container->expects($this->once())->method('has')->willReturn(true);
+ $this->container->expects($this->once())->method('get')->willReturn(['form']);
+
+ $config = $this->callMethod($this->subject, 'getConfig', $this->container);
+
+ $this->assertSame([], $config);
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetValidConfig(): void
+ {
+ $config = ['dot_form' => ['form_name']];
+ $this->container->expects($this->once())->method('has')->willReturn(true);
+ $this->container->expects($this->once())->method('get')->willReturn($config);
+
+ $result = $this->callMethod($this->subject, 'getConfig', $this->container);
+
+ $this->assertSame($config['dot_form'], $result);
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetConfigSubKey(): void
+ {
+ $config = ['dot_form' => ['forms' => ['form_name']]];
+ $this->container->expects($this->once())->method('has')->willReturn(true);
+ $this->container->expects($this->once())->method('get')->willReturn($config);
+
+ $result = $this->callMethod($this->subject, 'getConfig', $this->container);
+
+ $this->assertSame($config['dot_form']['forms'], $result);
+ }
+
+ /**
+ * @throws Exception
+ * @throws ReflectionException
+ */
+ public function testGetExistingFormFactory(): void
+ {
+ $formFactory = $this->createMock(Factory::class);
+ $reflectionClass = new ReflectionClass(FormAbstractServiceFactory::class);
+ $reflectionClass->getProperty('factory')->setValue($this->subject, $formFactory);
+
+ $result = $reflectionClass
+ ->getMethod('getFormFactory')
+ ->invoke($this->subject, $this->container);
+
+ $this->assertInstanceOf(Factory::class, $result);
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetFormFactoryFormElementManagerNotFound(): void
+ {
+ $this->container->expects($this->once())->method('has')->willReturn(false);
+
+ $result = $this->callMethod($this->subject, 'getFormFactory', $this->container);
+ $reflectionClass = new ReflectionClass($result);
+
+ $this->assertInstanceOf(Factory::class, $result);
+ $this->assertNull($reflectionClass->getProperty('formElementManager')->getValue($result));
+ }
+
+ /**
+ * @throws Exception
+ * @throws ReflectionException
+ */
+ public function testGetFormFactoryExistingFormElementManager(): void
+ {
+ $formElementManager = $this->createMock(FormElementManager::class);
+ $this->container->expects($this->once())->method('has')->willReturn(true);
+ $this->container->expects($this->once())->method('get')->willReturn($formElementManager);
+
+ $result = $this->callMethod($this->subject, 'getFormFactory', $this->container);
+ $reflectionClass = new ReflectionClass($result);
+
+ $this->assertInstanceOf(Factory::class, $result);
+ $this->assertInstanceOf(
+ FormElementManager::class,
+ $reflectionClass->getProperty('formElementManager')->getValue($result)
+ );
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ private function callMethod(object $object, string $method, mixed ...$args): mixed
+ {
+ $reflectionClass = new ReflectionClass($object::class);
+
+ return $reflectionClass->getMethod($method)->invoke($object, ...$args);
+ }
+}
diff --git a/test/Factory/FormElementManagerFactoryTest.php b/test/Factory/FormElementManagerFactoryTest.php
new file mode 100644
index 0000000..e5482d5
--- /dev/null
+++ b/test/Factory/FormElementManagerFactoryTest.php
@@ -0,0 +1,35 @@
+createMock(ContainerInterface::class);
+ $container->expects($this->once())->method('get')->willReturn([
+ 'dot_form' => [
+ 'form_manager' => [],
+ ],
+ ]);
+
+ $formElementManagerFactory = (new FormElementManagerFactory())($container);
+
+ $this->assertInstanceOf(FormElementManager::class, $formElementManagerFactory);
+ }
+}