diff --git a/.github/workflows/coverage_report.yml b/.github/workflows/coverage_report.yml
index 3111954..02323d9 100644
--- a/.github/workflows/coverage_report.yml
+++ b/.github/workflows/coverage_report.yml
@@ -4,8 +4,23 @@ on:
push:
branches: [master]
jobs:
+ install_tools:
+ name: Install tools
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v7
+ - name: Install tools
+ uses: ngmy/phive-install-action@master
+ - name: Upload tools to artifact store
+ uses: actions/upload-artifact@v7
+ with:
+ name: tools
+ path: tools
+
coverage:
name: coverage
+ needs: install_tools
runs-on: ubuntu-latest
steps:
- name: Checkout
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index ee674d7..77ab1cd 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -16,15 +16,18 @@ jobs:
name: tools
path: tools
test:
- name: test
+ name: Test suite
needs: install_tools
strategy:
fail-fast: false
matrix:
- operating-system: ["ubuntu-latest", "macOs-latest"]
+ operating-system: ["ubuntu-latest", "macOs-latest", "windows-latest"]
php-versions: ["8.5"]
runs-on: ${{ matrix.operating-system }}
steps:
+ - name: Set autocrlf on windows
+ if: matrix.operating-system == 'windows-latest'
+ run: git config --global core.autocrlf false
- name: Checkout
uses: actions/checkout@v7
- name: Setup PHP, with composer and extensions
@@ -42,45 +45,9 @@ jobs:
with:
name: tools
path: tools
- - name: Set tools as an executable
- run: find tools -type f -print0 | xargs -0 chmod +x
- name: Check coding standard
run: composer cs:check
- name: Static analysis tool
run: composer analytics
- name: Test suite
run: composer test
- test-windows:
- name: test-windows
- needs: install_tools
- strategy:
- fail-fast: false
- matrix:
- php-versions: ["8.5"]
- runs-on: windows-latest
- steps:
- - name: Set autocrlf
- run: git config --global core.autocrlf false
- - name: Checkout
- uses: actions/checkout@v7
- - name: Setup PHP, with composer and extensions
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php-versions }}
- extensions: libxml, simplexml, dom
- coverage: none
- - name: Install composer dependencies
- uses: ramsey/composer-install@v4
- with:
- composer-options: "--prefer-dist --optimize-autoloader"
- - name: Download tools from artifact store
- uses: actions/download-artifact@v7
- with:
- name: tools
- path: tools
- - name: Check coding standard
- run: php tools/php-cs-fixer fix -v --diff --dry-run
- - name: Static analysis tool
- run: php tools/phpstan analyze
- - name: Test suite
- run: composer test
diff --git a/.phive/phars.xml b/.phive/phars.xml
index a2d4939..a87ac73 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -2,4 +2,5 @@
+
diff --git a/composer.json b/composer.json
index f17eeff..5d50b0c 100644
--- a/composer.json
+++ b/composer.json
@@ -27,36 +27,28 @@
}
},
"require-dev": {
- "pestphp/pest": "^5",
"mikey179/vfsstream": "^1.6"
},
"scripts": {
- "analytics": "tools/phpstan",
+ "analytics": "php tools/phpstan",
"check": [
"@test",
"@analytics",
"@cs:fix"
],
- "coverage": "@test --coverage",
"coverage:html": "@test --coverage-html coverage/",
"coverage:clover": "@test --coverage-clover clover.xml",
- "cs:check": "tools/php-cs-fixer fix -v --diff --dry-run",
- "cs:fix": "tools/php-cs-fixer fix -v --diff",
- "test": "pest"
+ "cs:check": "php tools/php-cs-fixer fix -v --diff --dry-run",
+ "cs:fix": "php tools/php-cs-fixer fix -v --diff",
+ "test": "php tools/phpunit"
},
"scripts-descriptions": {
"analytics": "Run static analysis tool",
"check": "Perform all tests and analysis, required before submitting a pull request",
"cs:check": "Run code style analysis, without fixing errors",
"cs:fix": "Run code style analysis and fix errors",
- "coverage": "Show coverage report to the console",
"coverage:html": "Create a code coverage report in html format, into the `coverage/` directory",
"coverage:clover": "Create a code coverage report in xml format, into the `clover.xml` file",
"test": "Run the test suite"
- },
- "config": {
- "allow-plugins": {
- "pestphp/pest-plugin": true
- }
}
}
diff --git a/tests/Datasets/Inclusion.php b/tests/Datasets/Inclusion.php
deleted file mode 100644
index a74243b..0000000
--- a/tests/Datasets/Inclusion.php
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
- ",
- "
-
-
- ",
- [
- 'name' => 'named',
- 'defaultIdMethod' => 'native',
- 'table' => [
- 'name' => 'book',
- 'phpName' => 'Book',
- ],
- ],
- ],
-]);
diff --git a/tests/Datasets/Xml.php b/tests/Datasets/Xml.php
deleted file mode 100644
index 70de153..0000000
--- a/tests/Datasets/Xml.php
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
- Star Wars
- True
- 32.5
-
-
- The Lord Of The Rings
- false
-
-
-"
- ,
- ['movie' => [0 => ['title' => 'Star Wars', 'starred' => true, 'percentage' => 32.5], 1 => ['title' => 'The Lord Of The Rings', 'starred' => false]]],
- ],
- [
- "
-
-
-
- stream
- /var/log/default.log
- 300
-
-
- stream
- /var/log/bookstore.log
-
-
-", [
- 'log' => [
- 'logger' => [
- [
- 'name' => 'defaultLogger',
- 'type' => 'stream',
- 'path' => '/var/log/default.log',
- 'level' => 300,
- ],
- [
- 'name' => 'bookstore',
- 'type' => 'stream',
- 'path' => '/var/log/bookstore.log',
- ],
- ],
- ]],
- ],
- [
- "
-
-
-
-
-", [
- 'database' => [
- 'name' => 'TestDb',
- 'table' => [
- 0 => ['name' => 'table1'],
- 1 => ['name' => 'table2'],
- ],
- ],
- ],
- ],
- [
- 'foo',
- ['node' => 'foo'],
- ],
- [
- '',
- ['node' => ['foo' => 'bar']],
- ],
- [
- '0',
- ['node' => 0],
- ],
- [
- '',
- ['node' => null],
- ],
- [
- 'Hello World!]]>',
- ['node' => 'Hello World!'],
- ],
-]);
diff --git a/tests/Datasets/XmlNoTypes.php b/tests/Datasets/XmlNoTypes.php
deleted file mode 100644
index c3973de..0000000
--- a/tests/Datasets/XmlNoTypes.php
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
- Star Wars
- True
- 32.5
-
-
- The Lord Of The Rings
- false
-
-
-"
- ,
- ['movie' => [0 => ['title' => 'Star Wars', 'starred' => 'True', 'percentage' => '32.5'], 1 => ['title' => 'The Lord Of The Rings', 'starred' => 'false']]],
- ],
- [
- "
-
-
-
- stream
- /var/log/default.log
- 300
-
-
- stream
- /var/log/bookstore.log
-
-
-", [
- 'log' => [
- 'logger' => [
- [
- 'name' => 'defaultLogger',
- 'type' => 'stream',
- 'path' => '/var/log/default.log',
- 'level' => '300',
- ],
- [
- 'name' => 'bookstore',
- 'type' => 'stream',
- 'path' => '/var/log/bookstore.log',
- ],
- ],
- ]],
- ],
- [
- "
-
-
-
-
-", [
- 'database' => [
- 'name' => 'TestDb',
- 'table' => [
- 0 => ['name' => 'table1'],
- 1 => ['name' => 'table2'],
- ],
- ],
- ],
- ],
-]);
diff --git a/tests/Datasets/XmlWithAttributes.php b/tests/Datasets/XmlWithAttributes.php
deleted file mode 100644
index 98c0337..0000000
--- a/tests/Datasets/XmlWithAttributes.php
+++ /dev/null
@@ -1,80 +0,0 @@
-
-
-
-
- stream
- /var/log/default.log
- 300
-
-
- stream
- /var/log/bookstore.log
-
-
-", [
- 'log' => [
- 'logger' => [
- [
- '@attributes' => [
- 'name' => 'defaultLogger',
- ],
- 'type' => 'stream',
- 'path' => '/var/log/default.log',
- 'level' => 300,
- ],
- [
- '@attributes' => [
- 'name' => 'bookstore',
- ],
- 'type' => 'stream',
- 'path' => '/var/log/bookstore.log',
- ],
- ],
- ]],
- ],
- [
- "
-
-
-
-
-", [
- 'database' => [
- '@attributes' => [
- 'name' => 'TestDb',
- ],
- 'table' => [
- 0 => [
- '@attributes' => [
- 'name' => 'table1',
- ],
- ],
- 1 => [
- '@attributes' => [
- 'name' => 'table2',
- ],
- ],
- ],
- ],
- ],
- ],
-]);
diff --git a/tests/Functional/ConversionTest.php b/tests/Functional/ConversionTest.php
index 0b3f88d..dca5e88 100644
--- a/tests/Functional/ConversionTest.php
+++ b/tests/Functional/ConversionTest.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
/*
- * Copyright (c) Cristiano Cinotti 2024 - 2025.
+ * Copyright (c) Cristiano Cinotti 2024 - 2026.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,14 +15,24 @@
* limitations under the License.
*/
+namespace Susina\XmlToArray\Tests\Functional;
+
+use PHPUnit\Framework\Attributes\DataProviderExternal;
+use PHPUnit\Framework\TestCase;
use Susina\XmlToArray\Converter;
+use Susina\XmlToArray\Tests\XmlToArrayDataProvider;
-it('converts real life XML files', function (string $file) {
- $phpFile = __DIR__ . "/../Fixtures/$file.php";
- $xmlFile = __DIR__ . "/../Fixtures/$file.xml";
+class ConversionTest extends TestCase
+{
+ #[DataProviderExternal(XmlToArrayDataProvider::class, 'realCaseProvider')]
+ public function testRealLifeXmlConversion(string $file): void
+ {
+ $phpFile = __DIR__ . "/../Fixtures/$file.php";
+ $xmlFile = __DIR__ . "/../Fixtures/$file.xml";
- $expected = include($phpFile);
- $actual = Converter::create()->convert(file_get_contents($xmlFile));
+ $expected = include($phpFile);
+ $actual = Converter::create()->convert(file_get_contents($xmlFile));
- expect($actual)->toBe($expected);
-})->with(['joomla', 'propel']);
+ $this->assertSame($expected, $actual);
+ }
+}
diff --git a/tests/Pest.php b/tests/Pest.php
deleted file mode 100644
index c9730f4..0000000
--- a/tests/Pest.php
+++ /dev/null
@@ -1,17 +0,0 @@
-in('Unit');
diff --git a/tests/Unit/ConverterTest.php b/tests/Unit/ConverterTest.php
index 57252b0..5bbb29a 100644
--- a/tests/Unit/ConverterTest.php
+++ b/tests/Unit/ConverterTest.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
/*
- * Copyright (c) Cristiano Cinotti 2024 - 2025.
+ * Copyright (c) Cristiano Cinotti 2024 - 2026.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,42 +15,80 @@
* limitations under the License.
*/
+namespace Susina\XmlToArray\Tests\Unit;
+
use org\bovigo\vfs\vfsStream;
+use PHPUnit\Framework\Attributes\DataProviderExternal;
use Susina\XmlToArray\Exception\ConverterException;
use Susina\XmlToArray\Converter;
+use Susina\XmlToArray\Tests\VfsTestCase;
+use Susina\XmlToArray\Tests\XmlToArrayDataProvider;
+
+class ConverterTest extends VfsTestCase
+{
+ private Converter $converter;
+ public function setUp(): void
+ {
+ $this->converter = new Converter();
+ }
+
+ public function testStaticConstructor(): void
+ {
+ $this->assertInstanceOf(Converter::class, Converter::create());
+ }
+
+ #[DataProviderExternal(XmlToArrayDataProvider::class, 'xmlProvider')]
+ public function testConvertXmlToArray(string $xml, array $expected): void
+ {
+ $actual = $this->converter->convert($xml);
+ $this->assertSame($expected, $actual);
+ }
+
+ public function testConvertXmlWithInclusions(): void
+ {
+ $xmlLoad = "
+
+ getIncludedFile()->url()}\" xpointer=\"xpointer( /database/* )\"
+ />
+";
+ $expected = [
+ 'name' => 'named',
+ 'defaultIdMethod' => 'native',
+ 'table' => [
+ 'name' => 'book',
+ 'phpName' => 'Book',
+ ],
+ ];
+ $actual = $this->converter->convert($xmlLoad);
-beforeEach(function () {
- $this->converter = new Converter();
-});
-
-it('instantiate the correct class, via static constructor', function () {
- expect(Converter::create())->toBeInstanceOf(Converter::class);
-});
-
-it('converts xml to array', function (string $xml, array $expected) {
- $actual = $this->converter->convert($xml);
- expect($actual)->toBe($expected);
-})->with('Xml');
-
-it('converts xml with inclusion', function (string $xmlLoad, string $xmlInclude, array $expected) {
- vfsStream::newFile('testconvert_include.xml')->at($this->getRoot())->setContent($xmlInclude);
- $actual = $this->converter->convert($xmlLoad);
- expect($actual)->toBe($expected);
-})->with('Inclusion');
+ $this->assertSame($expected, $actual);
+ }
-it('converts an invalid xml', function () {
- $invalidXml = <<< INVALID_XML
+ public function testInvalidXmlThrowsException(): void
+ {
+ $this->expectException(ConverterException::class);
+ $this->expectExceptionMessageIsOrContains(
+ "An error occurred while parsing XML string:
+ - Fatal 4: Start tag expected, '<' not found
+",
+ );
+ $invalidXml = <<< INVALID_XML
No xml
only plain text
---------
INVALID_XML;
- $this->converter->convert($invalidXml);
-})->throws(ConverterException::class, "An error occurred while parsing XML string:
- - Fatal 4: Start tag expected, '<' not found
-");
-it('finds error in xml content', function () {
- $xmlWithError = <<< XML
+ $this->converter->convert($invalidXml);
+ }
+
+ public function testXmlContentErrorThrowsException(): void
+ {
+ $this->expectException(ConverterException::class);
+ $this->expectExceptionMessageIsOrContains("An error occurred while parsing XML string:
+ - Fatal 76: Opening and ending tag mismatch: titles line 4 and title
+");
+ $xmlWithError = <<< XML
@@ -61,13 +99,21 @@
XML;
- $this->converter->convert($xmlWithError);
-})->throws(ConverterException::class, "An error occurred while parsing XML string:
+
+ $this->converter->convert($xmlWithError);
+ }
+
+ public function testMultipleXmlErrorsThrowsException(): void
+ {
+ $this->expectException(ConverterException::class);
+ $this->expectExceptionMessageIsOrContains(
+ "Some errors occurred while parsing XML string:
- Fatal 76: Opening and ending tag mismatch: titles line 4 and title
-");
+ - Fatal 76: Opening and ending tag mismatch: movies line 2 and moviess
+",
+ );
-it('finds multiple errors in xml', function () {
- $xmlWithErrors = <<< XML
+ $xmlWithErrors = <<< XML
@@ -78,103 +124,88 @@
XML;
- $this->converter->convert($xmlWithErrors);
-})->throws(ConverterException::class, "Some errors occurred while parsing XML string:
- - Fatal 76: Opening and ending tag mismatch: titles line 4 and title
- - Fatal 76: Opening and ending tag mismatch: movies line 2 and moviess
-");
-it('converts an XML string without merging @attributes key', function (string $xml, array $expected) {
- $actual = Converter::create(['mergeAttributes' => false])->convert($xml);
- expect($actual)->toBe($expected);
-})->with('XmlWithAttributes');
-
-it('converts an XML string without preserving data types', function (string $xml, array $expected) {
- $actual = Converter::create(['typesAsString' => true])->convert($xml);
- expect($actual)->toBe($expected);
-})->with('XmlNoTypes');
-
-it('converts an XML string preserving the first tag', function () {
- $expected = [
- 'breakfast_menu' => [
- 'food' => [
- 'name' => 'Waffles',
+ $this->converter->convert($xmlWithErrors);
+ }
+
+ #[DataProviderExternal(XmlToArrayDataProvider::class, 'xmlWithAttributesProvider')]
+ public function testConvertXmlWithoutMergingAttributes(string $xml, array $expected): void
+ {
+ $actual = Converter::create(['mergeAttributes' => false])->convert($xml);
+ $this->assertSame($expected, $actual);
+ }
+
+ #[DataProviderExternal(XmlToArrayDataProvider::class, 'xmlNoTypesProvider')]
+ public function testConvertXmlWithoutPreservingDataTypes(string $xml, array $expected): void
+ {
+ $actual = Converter::create(['typesAsString' => true])->convert($xml);
+ $this->assertSame($expected, $actual);
+ }
+
+ public function testConvertiXmlPreservingTheFirstTag(): void
+ {
+ $expected = [
+ 'breakfast_menu' => [
+ 'food' => [
+ 'name' => 'Waffles',
+ ],
],
- ],
- ];
+ ];
- $xml = "
+ $xml = "
Waffles
-";
-
- $actual = Converter::create(['preserveFirstTag' => true])->convert($xml);
- expect($actual)->toBe($expected);
-});
-
-it('converts an xml string and save to a file', function (string $xml, array $expected, string $content) {
- $file = vfsStream::newFile('saved_file.php')->at($this->getRoot());
-
- $this->converter->convertAndSave($xml, $file->url());
-
- $actual = include($file->url());
-
- expect($actual)->toBe($expected)
- ->and($content)->toBe($file->getContent());
-})->with([
- ["
-
-
- Star Wars
- True
- 32.5
-
-
- The Lord Of The Rings
- false
-
-
-",
- [
- 'movie' => [
- 0 => ['title' => 'Star Wars', 'starred' => true, 'percentage' => 32.5],
- 1 => ['title' => 'The Lord Of The Rings', 'starred' => false],
- ],
- ],
- "
- array (
- 0 =>
- array (
- 'title' => 'Star Wars',
- 'starred' => true,
- 'percentage' => 32.5,
- ),
- 1 =>
- array (
- 'title' => 'The Lord Of The Rings',
- 'starred' => false,
- ),
- ),
-);
-",
- ],
-]);
-
-it('try to save in a not existent directory', function () {
- $xml = "The Lord Of The Ringsfalse";
- $this->converter->convertAndSave($xml, $this->getRoot()->url() . '/my_dir/my_array.php');
-})->throws(\RuntimeException::class, "The directory `vfs://root/my_dir` does not exist: you should create it before writing a file.");
-
-it('try to save in a not writeable directory', function () {
- $dir = vfsStream::newDirectory('xml_dir', 000)->at($this->getRoot());
- $xml = "The Lord Of The Ringsfalse";
- $this->converter->convertAndSave($xml, $dir->url() . '/my_array.php');
-})->throws(\RuntimeException::class, "It's impossible to write into `vfs://root/xml_dir` directory: do you have the correct permissions?");
+"
+ ;
+ $actual = Converter::create(['preserveFirstTag' => true])->convert($xml);
+
+ $this->assertSame($expected, $actual);
+ }
+
+ #[DataProviderExternal(XmlToArrayDataProvider::class, 'convertAndSaveProvider')]
+ public function testConvertXmlAndSavesIntoExistentFile(string $xml, array $expectedArray, string $expectedContent): void
+ {
+ $file = $this->createFile('saved_file.php');
+
+ $this->converter->convertAndSave($xml, $file->url());
+ $actual = include($file->url());
+
+ $this->assertSame($expectedArray, $actual);
+ $this->assertSame($expectedContent, $file->getContent());
+ $this->assertSame($expectedContent, file_get_contents($file->url()));
+ }
+
+ #[DataProviderExternal(XmlToArrayDataProvider::class, 'convertAndSaveProvider')]
+ public function testConvertAndSaveCreatesOutputFileIfNotExistent(string $xml, array $expectedArray, string $expectedContent): void
+ {
+ $this->converter->convertAndSave($xml, $this->root->url() . '/my_saved_file.php');
+
+ $this->assertFileExists('vfs://root/my_saved_file.php');
+
+ $actual = include($this->root->url() . '/my_saved_file.php');
+
+ $this->assertSame($expectedArray, $actual);
+ $this->assertSame($expectedContent, file_get_contents($this->root->url() . '/my_saved_file.php'));
+ }
+
+ public function testSaveInNotExistentDirectoryThrowsException(): void
+ {
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessageIs("The directory `vfs://root/my_dir` does not exist: you should create it before writing a file.");
+
+ $xml = "The Lord Of The Ringsfalse";
+ $this->converter->convertAndSave($xml, $this->root->url() . '/my_dir/my_array.php');
+ }
+
+ public function testSaveInNotWriteableDirectoryThrowsException(): void
+ {
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessageIs("It's impossible to write into `vfs://root/xml_dir` directory: do you have the correct permissions?");
+
+ $dir = vfsStream::newDirectory('xml_dir', 000)->at($this->root);
+ $xml = "The Lord Of The Ringsfalse";
+ $this->converter->convertAndSave($xml, $dir->url() . '/my_array.php');
+ }
+}
diff --git a/tests/Unit/FileConverterTest.php b/tests/Unit/FileConverterTest.php
index 1f80e4d..dc7a40a 100644
--- a/tests/Unit/FileConverterTest.php
+++ b/tests/Unit/FileConverterTest.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
/*
- * Copyright (c) Cristiano Cinotti 2024 - 2025.
+ * Copyright (c) Cristiano Cinotti 2024 - 2026.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,147 +15,92 @@
* limitations under the License.
*/
+namespace Susina\XmlToArray\Tests\Unit;
+
use org\bovigo\vfs\vfsStream;
+use PHPUnit\Framework\Attributes\DataProviderExternal;
+use Susina\XmlToArray\Tests\VfsTestCase;
use Susina\XmlToArray\FileConverter;
-
-it('converts an XML file to an array', function (string $xml, array $expected) {
- $file = vfsStream::newFile("test_file.xml")->at($this->getRoot())->setContent($xml);
- $actual = FileConverter::create()->convert($file->url());
-
- expect($expected)->toBe($actual);
-})->with('Xml');
-
-it('try to convert a not existent file', function () {
- $converter = new FileConverter();
- $converter->convert('vfs://root/notexistent.xml');
-})->throws(\RuntimeException::class, 'The file `vfs://root/notexistent.xml` does not exist.');
-
-it('try to convert a not readable file', function () {
- $file = vfsStream::newFile('notreadable.xml', 200)->at($this->getRoot())->setContent("");
- FileConverter::create()->convert($file->url());
-})->throws(\RuntimeException::class, 'The file `vfs://root/notreadable.xml` is not readable: do you have the correct permissions?');
-
-it('converts an xml file into an array and save to a file', function (string $xml, array $expected, string $content) {
- $xmlFile = vfsStream::newFile('xml_file.xml')->at($this->getRoot())->setContent($xml);
- $saveFile = vfsStream::newFile('saved_file.php')->at($this->getRoot());
-
- FileConverter::create()->convertAndSave($xmlFile->url(), $saveFile->url());
-
- $actual = include($saveFile->url());
-
- expect($actual)->toBe($expected)
- ->and($content)->toBe($saveFile->getContent());
-})->with([
- ["
-
-
- Star Wars
- True
- 32.5
-
-
- The Lord Of The Rings
- false
-
-
-",
- [
- 'movie' => [
- 0 => ['title' => 'Star Wars', 'starred' => true, 'percentage' => 32.5],
- 1 => ['title' => 'The Lord Of The Rings', 'starred' => false],
- ],
- ],
- "
- array (
- 0 =>
- array (
- 'title' => 'Star Wars',
- 'starred' => true,
- 'percentage' => 32.5,
- ),
- 1 =>
- array (
- 'title' => 'The Lord Of The Rings',
- 'starred' => false,
- ),
- ),
-);
-",
- ],
-]);
-
-it('converts an xml string and save to a file, creating it', function (string $xml, array $expected, string $content) {
- $xmlFile = vfsStream::newFile('xml_file.xml')->at($this->getRoot())->setContent($xml);
- FileConverter::create()->convertAndSave($xmlFile->url(), $this->getRoot()->url() . '/save_file.php');
- expect('vfs://root/save_file.php')->toBeFile();
-
- $actual = include('vfs://root/save_file.php');
-
- expect($actual)->toBe($expected)
- ->and($content)->toBe(file_get_contents('vfs://root/save_file.php'));
-})->with([
- ["
-
-
- Star Wars
- True
- 32.5
-
-
- The Lord Of The Rings
- false
-
-
-",
- [
- 'movie' => [
- 0 => ['title' => 'Star Wars', 'starred' => true, 'percentage' => 32.5],
- 1 => ['title' => 'The Lord Of The Rings', 'starred' => false],
- ],
- ],
- "
- array (
- 0 =>
- array (
- 'title' => 'Star Wars',
- 'starred' => true,
- 'percentage' => 32.5,
- ),
- 1 =>
- array (
- 'title' => 'The Lord Of The Rings',
- 'starred' => false,
- ),
- ),
-);
-",
- ],
-]);
-
-it('try to save in a not existent directory', function () {
- $xmlFile = vfsStream::newFile('xml_file.xml')
- ->at($this->getRoot())
- ->setContent("The Lord Of The Ringsfalse");
- $converter = new FileConverter();
- $converter->convertAndSave($xmlFile->url(), $this->getRoot()->url() . '/my_dir/my_array.php');
-})->throws(\RuntimeException::class, "The directory `vfs://root/my_dir` does not exist: you should create it before writing a file.");
-
-it('try to save in a not writeable directory', function () {
- $dir = vfsStream::newDirectory('xml_dir', 000)->at($this->getRoot());
- $xmlFile = vfsStream::newFile('xml_file.xml')
- ->at($this->getRoot())
- ->setContent("The Lord Of The Ringsfalse");
- FileConverter::create()->convertAndSave($xmlFile->url(), $dir->url() . '/my_array.php');
-})->throws(\RuntimeException::class, "It's impossible to write into `vfs://root/xml_dir` directory: do you have the correct permissions?");
+use Susina\XmlToArray\Tests\XmlToArrayDataProvider;
+
+class FileConverterTest extends VfsTestCase
+{
+ #[DataProviderExternal(XmlToArrayDataProvider::class, 'xmlProvider')]
+ public function testConvertXmlFileToArray(string $xml, array $expected): void
+ {
+ $file = $this->createFile('test_file.xml', $xml);
+ $actual = FileConverter::create()->convert($file->url());
+
+ $this->assertSame($expected, $actual);
+ }
+
+ public function testConvertNotExistentXmlFileThrowsException(): void
+ {
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessageIs('The file `vfs://root/notexistent.xml` does not exist.');
+ FileConverter::create()->convert('vfs://root/notexistent.xml');
+ }
+
+ public function testConvertNotReadableXmlFileThrowsException(): void
+ {
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessageIs('The file `vfs://root/notreadable.xml` is not readable: do you have the correct permissions?');
+
+ $file = $this->createFile('notreadable.xml', '');
+ $file->chmod(000);
+
+ FileConverter::create()->convert($file->url());
+ }
+
+ #[DataProviderExternal(XmlToArrayDataProvider::class, 'convertAndSaveProvider')]
+ public function testConvertXmlFileAndSaveIntoAnotherFile(string $xml, array $expectedArray, string $expectedContent): void
+ {
+ $xmlFile = $this->createFile('xml_file.xml', $xml);
+ $saveFile = $this->createFile('saved_file.php');
+
+ $converter = new FileConverter();
+ $converter->convertAndSave($xmlFile->url(), $saveFile->url());
+ $actual = include($saveFile->url());
+
+ $this->assertSame($expectedArray, $actual);
+ $this->assertSame($expectedContent, $saveFile->getContent());
+ $this->assertSame($expectedContent, file_get_contents($saveFile->url()));
+ }
+
+ #[DataProviderExternal(XmlToArrayDataProvider::class, 'convertAndSaveProvider')]
+ public function testConvertAndSaveCreatesOutputFileIfNotExistent(string $xml, array $expectedArray, string $expectedContent): void
+ {
+ $xmlFile = $this->createFile('xml_file.xml', $xml);
+
+ $converter = new FileConverter();
+ $converter->convertAndSave($xmlFile->url(), $this->root->url() . '/my_saved_file.php');
+
+ $this->assertFileExists('vfs://root/my_saved_file.php');
+
+ $actual = include($this->root->url() . '/my_saved_file.php');
+
+ $this->assertSame($expectedArray, $actual);
+ $this->assertSame($expectedContent, file_get_contents($this->root->url() . '/my_saved_file.php'));
+ }
+
+ public function testSaveInNotExistentDirectoryThrowsException(): void
+ {
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessageIs("The directory `vfs://root/my_dir` does not exist: you should create it before writing a file.");
+
+ $xmlFile = $this->createFile('xml_file.xml', "The Lord Of The Ringsfalse");
+ $converter = new FileConverter();
+ $converter->convertAndSave($xmlFile->url(), $this->root->url() . '/my_dir/my_array.php');
+ }
+
+ public function testSaveInNotWriteableDirectoryThrowsException(): void
+ {
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessageIs("It's impossible to write into `vfs://root/xml_dir` directory: do you have the correct permissions?");
+
+ $dir = vfsStream::newDirectory('xml_dir', 000)->at($this->root);
+ $xmlFile = $this->createFile('xml_file.xml', "The Lord Of The Ringsfalse");
+ $converter = new FileConverter();
+ $converter->convertAndSave($xmlFile->url(), $dir->url() . '/my_array.php');
+ }
+}
diff --git a/tests/VfsTestCase.php b/tests/VfsTestCase.php
new file mode 100644
index 0000000..9891dd7
--- /dev/null
+++ b/tests/VfsTestCase.php
@@ -0,0 +1,68 @@
+ $this->root ??= vfsStream::setup();
+ }
+
+ /**
+ * Create a vfsStreamFile based on $path parameter.
+ * It creates the directory structure, too.
+ *
+ * @param string $path
+ * @param string $content
+ * @return vfsStreamFile
+ */
+ public function createFile(string $path, string $content = ''): vfsStreamFile
+ {
+ $dirs = explode('/', $path);
+ $fileName = array_pop($dirs);
+ $currentDir = $this->root;
+
+ foreach ($dirs as $dir) {
+ if (!$currentDir->hasChild($dir)) {
+ $currentDir->addChild(vfsStream::newDirectory($dir));
+ }
+ $currentDir = $currentDir->getChild($dir);
+ }
+
+ $file = vfsStream::newFile($fileName)->withContent($content);
+ $currentDir->addChild($file);
+
+ return $file;
+ }
+
+ public function getIncludedFile(): vfsStreamFile
+ {
+ return vfsStream::newFile('testconvert_include.xml')
+ ->at($this->root)
+ ->setContent("
+
+
+")
+ ;
+ }
+}
diff --git a/tests/VfsTrait.php b/tests/VfsTrait.php
deleted file mode 100644
index 5921eeb..0000000
--- a/tests/VfsTrait.php
+++ /dev/null
@@ -1,28 +0,0 @@
-root === null) {
- $this->root = vfsStream::setup();
- }
-
- return $this->root;
- }
-}
diff --git a/tests/XmlToArrayDataProvider.php b/tests/XmlToArrayDataProvider.php
new file mode 100644
index 0000000..ff2e901
--- /dev/null
+++ b/tests/XmlToArrayDataProvider.php
@@ -0,0 +1,298 @@
+
+
+
+ Star Wars
+ True
+ 32.5
+
+
+ The Lord Of The Rings
+ false
+
+
+ "
+ ,
+ ['movie' => [0 => ['title' => 'Star Wars', 'starred' => true, 'percentage' => 32.5], 1 => ['title' => 'The Lord Of The Rings', 'starred' => false]]],
+ ];
+ yield [
+ "
+
+
+
+ stream
+ /var/log/default.log
+ 300
+
+
+ stream
+ /var/log/bookstore.log
+
+
+ ", [
+ 'log' => [
+ 'logger' => [
+ [
+ 'name' => 'defaultLogger',
+ 'type' => 'stream',
+ 'path' => '/var/log/default.log',
+ 'level' => 300,
+ ],
+ [
+ 'name' => 'bookstore',
+ 'type' => 'stream',
+ 'path' => '/var/log/bookstore.log',
+ ],
+ ],
+ ]],
+ ];
+ yield [
+ "
+
+
+
+
+ ", [
+ 'database' => [
+ 'name' => 'TestDb',
+ 'table' => [
+ 0 => ['name' => 'table1'],
+ 1 => ['name' => 'table2'],
+ ],
+ ],
+ ],
+ ];
+ yield [
+ 'foo',
+ ['node' => 'foo'],
+ ];
+ yield [
+ '',
+ ['node' => ['foo' => 'bar']],
+ ];
+ yield [
+ '0',
+ ['node' => 0],
+ ];
+ yield [
+ '',
+ ['node' => null],
+ ];
+ yield [
+ 'Hello World!]]>',
+ ['node' => 'Hello World!'],
+ ];
+ }
+
+ public static function xmlNoTypesProvider(): Generator
+ {
+ yield [
+ "
+
+
+ Star Wars
+ True
+ 32.5
+
+
+ The Lord Of The Rings
+ false
+
+
+ "
+ ,
+ ['movie' => [0 => ['title' => 'Star Wars', 'starred' => 'True', 'percentage' => '32.5'], 1 => ['title' => 'The Lord Of The Rings', 'starred' => 'false']]],
+ ];
+ yield [
+ "
+
+
+
+ stream
+ /var/log/default.log
+ 300
+
+
+ stream
+ /var/log/bookstore.log
+
+
+ ", [
+ 'log' => [
+ 'logger' => [
+ [
+ 'name' => 'defaultLogger',
+ 'type' => 'stream',
+ 'path' => '/var/log/default.log',
+ 'level' => '300',
+ ],
+ [
+ 'name' => 'bookstore',
+ 'type' => 'stream',
+ 'path' => '/var/log/bookstore.log',
+ ],
+ ],
+ ]],
+ ];
+ yield [
+ "
+
+
+
+
+ ", [
+ 'database' => [
+ 'name' => 'TestDb',
+ 'table' => [
+ 0 => ['name' => 'table1'],
+ 1 => ['name' => 'table2'],
+ ],
+ ],
+ ],
+ ];
+ }
+
+ public static function xmlWithAttributesProvider(): Generator
+ {
+ yield [
+ "
+
+
+
+ stream
+ /var/log/default.log
+ 300
+
+
+ stream
+ /var/log/bookstore.log
+
+
+ ", [
+ 'log' => [
+ 'logger' => [
+ [
+ '@attributes' => [
+ 'name' => 'defaultLogger',
+ ],
+ 'type' => 'stream',
+ 'path' => '/var/log/default.log',
+ 'level' => 300,
+ ],
+ [
+ '@attributes' => [
+ 'name' => 'bookstore',
+ ],
+ 'type' => 'stream',
+ 'path' => '/var/log/bookstore.log',
+ ],
+ ],
+ ]],
+ ];
+ yield [
+ "
+
+
+
+
+ ", [
+ 'database' => [
+ '@attributes' => [
+ 'name' => 'TestDb',
+ ],
+ 'table' => [
+ 0 => [
+ '@attributes' => [
+ 'name' => 'table1',
+ ],
+ ],
+ 1 => [
+ '@attributes' => [
+ 'name' => 'table2',
+ ],
+ ],
+ ],
+ ],
+ ],
+ ];
+ }
+
+ public static function convertAndSaveProvider(): Generator
+ {
+ yield [
+ "
+
+
+ Star Wars
+ True
+ 32.5
+
+
+ The Lord Of The Rings
+ false
+
+
+"
+ ,
+ [
+ 'movie' => [
+ 0 => ['title' => 'Star Wars', 'starred' => true, 'percentage' => 32.5],
+ 1 => ['title' => 'The Lord Of The Rings', 'starred' => false],
+ ],
+ ],
+ "
+ array (
+ 0 =>
+ array (
+ 'title' => 'Star Wars',
+ 'starred' => true,
+ 'percentage' => 32.5,
+ ),
+ 1 =>
+ array (
+ 'title' => 'The Lord Of The Rings',
+ 'starred' => false,
+ ),
+ ),
+);
+",
+ ];
+ }
+
+ public static function realCaseProvider(): Generator
+ {
+ yield ['propel'];
+ yield ['joomla'];
+ }
+}