diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 88af801..8befaeb 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -33,8 +33,18 @@ jobs:
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- - name: Install
+ - name: Install Composer dependencies
run: composer install --prefer-dist
+ # —— QA ✔️️ ———————————————————————————————————————————————————————————————
- name: Qualimetry
run: make qa
+
+ # —— Tests 🧪 ————————————————————————————————————————————————————————————
+ - name: Phpunit tests
+ run: XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-clover coverage.xml
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
+
+ - name: "Upload coverage to Codecov"
+ uses: codecov/codecov-action@v1
diff --git a/.gitignore b/.gitignore
index 7c43e86..109ec1c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,5 @@ composer.lock
/phpmetrics/
coverage.*
.php_cs.cache
+.phpunit.result.cache
+/var/
diff --git a/Makefile b/Makefile
index d13f082..9f323aa 100644
--- a/Makefile
+++ b/Makefile
@@ -54,8 +54,16 @@ metrics: ## Build static analysis from the php in src. Repports available in ./p
.PHONY: phpstan
phpstan: ## Launch PHP Static Analysis
- vendor/bin/phpstan analyse src --level=6
+ vendor/bin/phpstan analyse src tests --level=6 -c phpstan.neon
.PHONY: qa qualimetry
qa: qualimetry ## Launch all qualimetry rules
qualimetry: checkstyle lint-php cpd composer-validate metrics phpstan
+
+# ====================
+## Testing
+phpunit:
+ vendor/bin/phpunit
+
+phpunit-coverage:
+ XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-text
diff --git a/README.md b/README.md
index 4130ee8..2c166a1 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,7 @@
[![License](http://poser.pugx.org/smartbooster/parameter-bundle/license)](https://packagist.org/packages/smartbooster/parameter-bundle)
![CI workflow](https://github.com/smartbooster/parameter-bundle/actions/workflows/ci.yml/badge.svg)
+[![codecov](https://codecov.io/gh/smartbooster/parameter-bundle/branch/master/graph/badge.svg?token=QQZPRVXGL8)](https://codecov.io/gh/smartbooster/parameter-bundle)
## Installation
diff --git a/composer.json b/composer.json
index ca5bada..1373aa2 100644
--- a/composer.json
+++ b/composer.json
@@ -12,11 +12,21 @@
"homepage": "https://www.smartbooster.io"
}
],
+ "require": {
+ "php": "^7.4",
+ "symfony/http-kernel": "^4.4",
+ "symfony/config": "^4.4",
+ "symfony/yaml": "^4.4",
+ "symfony/dependency-injection": "^4.4"
+ },
"require-dev": {
"squizlabs/php_codesniffer": "^3.6",
"sebastian/phpcpd": "^6.0",
"phpmetrics/phpmetrics": "^2.7",
- "phpstan/phpstan": "^0.12.90"
+ "phpstan/phpstan": "^0.12.90",
+ "phpunit/phpunit": "^9.5",
+ "phpstan/phpstan-symfony": "^0.12.37",
+ "symfony/framework-bundle": "^4.4"
},
"autoload": {
"psr-4": {
diff --git a/src/.gitkeep b/config/.gitkeep
similarity index 100%
rename from src/.gitkeep
rename to config/.gitkeep
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..d7b3498
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,6 @@
+includes:
+ - vendor/phpstan/phpstan-symfony/extension.neon
+ - vendor/phpstan/phpstan-symfony/rules.neon
+
+parameters:
+ checkMissingIterableValueType: false
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..99ad480
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+ ./tests
+
+
+
+
+ ./src
+
+
+ ./src/SmartParameterBundle.php
+
+
+
diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php
new file mode 100644
index 0000000..53780f5
--- /dev/null
+++ b/src/DependencyInjection/Configuration.php
@@ -0,0 +1,41 @@
+
+ */
+class Configuration implements ConfigurationInterface
+{
+ public function getConfigTreeBuilder()
+ {
+ $treeBuilder = new TreeBuilder('smart_parameter');
+ $root = $treeBuilder->getRootNode();
+
+ $root
+ ->children()
+ ->append($this->getParametersNode())
+ ->end()
+ ;
+
+ return $treeBuilder;
+ }
+
+ private function getParametersNode(): NodeDefinition
+ {
+ return (new TreeBuilder('parameters'))->getRootNode()
+ ->requiresAtLeastOneElement()
+ ->useAttributeAsKey('name')
+ ->arrayPrototype()
+ ->children()
+ ->scalarNode('value')->isRequired()->end()
+ ->scalarNode('help')->end()
+ ->end()
+ ->end()
+ ;
+ }
+}
diff --git a/src/DependencyInjection/SmartParameterExtension.php b/src/DependencyInjection/SmartParameterExtension.php
new file mode 100644
index 0000000..6fe34b1
--- /dev/null
+++ b/src/DependencyInjection/SmartParameterExtension.php
@@ -0,0 +1,23 @@
+
+ */
+class SmartParameterExtension extends Extension
+{
+ /**
+ * @param array $configs
+ * @param ContainerBuilder $container
+ * @throws \Exception
+ * @return void
+ */
+ public function load(array $configs, ContainerBuilder $container)
+ {
+ $this->processConfiguration(new Configuration(), $configs);
+ }
+}
diff --git a/src/SmartParameterBundle.php b/src/SmartParameterBundle.php
new file mode 100644
index 0000000..9f94b05
--- /dev/null
+++ b/src/SmartParameterBundle.php
@@ -0,0 +1,16 @@
+
+ */
+class SmartParameterBundle extends Bundle
+{
+ public function getPath(): string
+ {
+ return \dirname(__DIR__);
+ }
+}
diff --git a/src/tmp.php b/src/tmp.php
deleted file mode 100644
index 0fb968e..0000000
--- a/src/tmp.php
+++ /dev/null
@@ -1,3 +0,0 @@
-
+ */
+class AppKernel extends Kernel
+{
+ public function registerBundles()
+ {
+ return [
+ new \Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
+ new SmartParameterBundle(),
+ ];
+ }
+
+ public function registerContainerConfiguration(LoaderInterface $loader): void
+ {
+ $loader->load(__DIR__ . '/../fixtures/config/full.yml');
+ }
+}
diff --git a/tests/App/AppKernelTest.php b/tests/App/AppKernelTest.php
new file mode 100644
index 0000000..3f749e5
--- /dev/null
+++ b/tests/App/AppKernelTest.php
@@ -0,0 +1,26 @@
+
+ *
+ * vendor/bin/phpunit tests/App/AppKernelTest.php
+ */
+class AppKernelTest extends WebTestCase
+{
+ protected static function getKernelClass()
+ {
+ return AppKernel::class;
+ }
+
+ public function testBootingKernel(): void
+ {
+ self::bootKernel();
+
+ $this->assertInstanceOf(KernelInterface::class, self::$kernel);
+ }
+}
diff --git a/tests/DependencyInjection/DependencyInjectionTest.php b/tests/DependencyInjection/DependencyInjectionTest.php
new file mode 100644
index 0000000..d47b1c4
--- /dev/null
+++ b/tests/DependencyInjection/DependencyInjectionTest.php
@@ -0,0 +1,84 @@
+
+ *
+ * vendor/bin/phpunit tests/DependencyInjection/DependencyInjectionTest.php
+ */
+class DependencyInjectionTest extends TestCase
+{
+ private ContainerBuilder $container;
+
+ protected function setUp(): void
+ {
+ $bundle = new SmartParameterBundle();
+ $this->container = new ContainerBuilder();
+
+ $this->container->setParameter('kernel.debug', true);
+ $this->container->setParameter('kernel.bundles', [
+ 'FrameworkBundle' => \Symfony\Bundle\FrameworkBundle\FrameworkBundle::class,
+ ]);
+ $this->container->setParameter('kernel.environment', 'test');
+
+ $this->container->registerExtension($bundle->getContainerExtension());
+ $bundle->build($this->container);
+ }
+
+ /**
+ * @dataProvider invalidConfigurationProvider
+ */
+ public function testInvalidConfigurationParsing(string $resource, string $message): void
+ {
+ $this->expectException(InvalidConfigurationException::class);
+ $this->expectExceptionMessage($message);
+
+ $loader = new YamlFileLoader($this->container, new FileLocator(__DIR__ . '/../fixtures/config/'));
+ $loader->load($resource . ".yml");
+ $this->container->compile();
+ }
+
+ public function invalidConfigurationProvider(): array
+ {
+ return [
+ 'invalid_no_parameter_defined' => [
+ 'ressource' => 'invalid_no_parameter_defined',
+ 'message' => 'The path "smart_parameter.parameters" should have at least 1 element(s) defined.',
+ ],
+ 'invalid_missing_parameter_value' => [
+ 'ressource' => 'invalid_missing_parameter_value',
+ 'message' => 'The child node "value" at path "smart_parameter.parameters.parameter_without_value" must be configured.',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider configurationProvider
+ */
+ public function testValidConfigurationParsing(string $resource): void
+ {
+ $loader = new YamlFileLoader($this->container, new FileLocator(__DIR__ . '/../fixtures/config/'));
+ $loader->load($resource . ".yml");
+ $this->container->compile();
+ // This assertion is already true with the setUp but it valid the fact that the container did compile with the given configuration
+ $this->assertNotNull($this->container->getExtension("smart_parameter"));
+ }
+
+ public function configurationProvider(): array
+ {
+ return [
+ 'full' => ['full'],
+ 'minimal' => ['minimal'],
+ 'none' => ['none'],
+ ];
+ }
+}
diff --git a/tests/fixtures/config/full.yml b/tests/fixtures/config/full.yml
new file mode 100644
index 0000000..aac4eb4
--- /dev/null
+++ b/tests/fixtures/config/full.yml
@@ -0,0 +1,11 @@
+# Full config fixture
+smart_parameter:
+ parameters:
+ # Textual paramter
+ dummy_support_emails:
+ value: "support@example.com, technical-support@example.com"
+ help: "This parameter is used by the mailer for support recipients. Format : Separate email by comma."
+ # Number parameter
+ dummy_homepage_cache_duration:
+ value: 3600
+ help: "This parameter is used by the backend to set the duration of cache applied to the Homepage. Set the duration in second."
diff --git a/tests/fixtures/config/invalid_missing_parameter_value.yml b/tests/fixtures/config/invalid_missing_parameter_value.yml
new file mode 100644
index 0000000..c47846b
--- /dev/null
+++ b/tests/fixtures/config/invalid_missing_parameter_value.yml
@@ -0,0 +1,4 @@
+#
+smart_parameter:
+ parameters:
+ parameter_without_value:
diff --git a/tests/fixtures/config/invalid_no_parameter_defined.yml b/tests/fixtures/config/invalid_no_parameter_defined.yml
new file mode 100644
index 0000000..d5bc9d2
--- /dev/null
+++ b/tests/fixtures/config/invalid_no_parameter_defined.yml
@@ -0,0 +1,3 @@
+#
+smart_parameter:
+ parameters:
diff --git a/tests/fixtures/config/minimal.yml b/tests/fixtures/config/minimal.yml
new file mode 100644
index 0000000..4524bbc
--- /dev/null
+++ b/tests/fixtures/config/minimal.yml
@@ -0,0 +1,5 @@
+# Config with only minimal parameter configuration
+smart_parameter:
+ parameters:
+ dummy_parameter:
+ value: "some value"
diff --git a/tests/fixtures/config/none.yml b/tests/fixtures/config/none.yml
new file mode 100644
index 0000000..acdf27c
--- /dev/null
+++ b/tests/fixtures/config/none.yml
@@ -0,0 +1,2 @@
+# Empty config
+smart_parameter: ~