spout/tests/Spout/Reader/XLSX/Helper/CellValueFormatterTest.php
2017-11-27 00:24:13 +01:00

208 lines
7.5 KiB
PHP

<?php
namespace Box\Spout\Reader\XLSX\Helper;
use Box\Spout\Common\Helper\Escaper;
use Box\Spout\Reader\Exception\InvalidValueException;
use Box\Spout\Reader\XLSX\Manager\StyleManager;
use PHPUnit\Framework\TestCase;
/**
* Class CellValueFormatterTest
*/
class CellValueFormatterTest extends TestCase
{
/**
* @return array
*/
public function dataProviderForTestExcelDate()
{
return [
// use 1904 dates, node value, expected date as string
// 1900 calendar
[false, 3687.4207639, '1910-02-03 10:05:54'],
[false, 2.5000000, '1900-01-01 12:00:00'],
[false, 2958465.9999884, '9999-12-31 23:59:59'],
[false, 2958465.9999885, null],
[false, -2337.999989, '1893-08-05 00:00:01'],
[false, -693593, '0001-01-01 00:00:00'],
[false, -693593.0000001, null],
[false, 0, '1899-12-30 00:00:00'],
[false, 0.25, '1899-12-30 06:00:00'],
[false, 0.5, '1899-12-30 12:00:00'],
[false, 0.75, '1899-12-30 18:00:00'],
[false, 0.99999, '1899-12-30 23:59:59'],
[false, 1, '1899-12-31 00:00:00'],
[false, '3687.4207639', '1910-02-03 10:05:54'],
// 1904 calendar
[true, 2225.4207639, '1910-02-03 10:05:54'],
[true, 2.5000000, '1904-01-03 12:00:00'],
[true, 2957003.9999884, '9999-12-31 23:59:59'],
[true, 2957003.9999885, null],
[true, -3799.999989, '1893-08-05 00:00:01'],
[true, -695055, '0001-01-01 00:00:00'],
[true, -695055.0000001, null],
[true, 0, '1904-01-01 00:00:00'],
[true, 0.25, '1904-01-01 06:00:00'],
[true, 0.5, '1904-01-01 12:00:00'],
[true, 0.75, '1904-01-01 18:00:00'],
[true, 0.99999, '1904-01-01 23:59:59'],
[true, 1, '1904-01-02 00:00:00'],
[true, '2225.4207639', '1910-02-03 10:05:54'],
];
}
/**
* @dataProvider dataProviderForTestExcelDate
*
* @param bool $shouldUse1904Dates
* @param int|float|string $nodeValue
* @param string|null $expectedDateAsString
* @return void
*/
public function testExcelDate($shouldUse1904Dates, $nodeValue, $expectedDateAsString)
{
$nodeListMock = $this->createMock(\DOMNodeList::class);
$nodeListMock
->expects($this->atLeastOnce())
->method('item')
->with(0)
->will($this->returnValue((object) ['nodeValue' => $nodeValue]));
$nodeMock = $this->createMock(\DOMElement::class);
$nodeMock
->expects($this->atLeastOnce())
->method('getAttribute')
->will($this->returnValueMap([
[CellValueFormatter::XML_ATTRIBUTE_TYPE, CellValueFormatter::CELL_TYPE_NUMERIC],
[CellValueFormatter::XML_ATTRIBUTE_STYLE_ID, 123],
]));
$nodeMock
->expects($this->atLeastOnce())
->method('getElementsByTagName')
->with(CellValueFormatter::XML_NODE_VALUE)
->will($this->returnValue($nodeListMock));
/** @var StyleManager|\PHPUnit_Framework_MockObject_MockObject $styleManagerMock */
$styleManagerMock = $this->createMock(StyleManager::class);
$styleManagerMock
->expects($this->once())
->method('shouldFormatNumericValueAsDate')
->with(123)
->will($this->returnValue(true));
$formatter = new CellValueFormatter(null, $styleManagerMock, false, $shouldUse1904Dates, new Escaper\XLSX());
try {
$result = $formatter->extractAndFormatNodeValue($nodeMock);
if ($expectedDateAsString === null) {
$this->fail('An exception should have been thrown');
} else {
$this->assertInstanceOf(\DateTime::class, $result);
$this->assertSame($expectedDateAsString, $result->format('Y-m-d H:i:s'));
}
} catch (InvalidValueException $exception) {
// do nothing
}
}
/**
* @return array
*/
public function dataProviderForTestFormatNumericCellValueWithNumbers()
{
// Some test values exceed PHP_INT_MAX on 32-bit PHP. They are
// therefore converted to as doubles automatically by PHP.
$expectedBigNumberType = (PHP_INT_SIZE < 8 ? 'double' : 'integer');
return [
[42, 42, 'integer'],
[42.5, 42.5, 'double'],
[-42, -42, 'integer'],
[-42.5, -42.5, 'double'],
['42', 42, 'integer'],
['42.5', 42.5, 'double'],
[865640023012945, 865640023012945, $expectedBigNumberType],
['865640023012945', 865640023012945, $expectedBigNumberType],
[865640023012945.5, 865640023012945.5, 'double'],
['865640023012945.5', 865640023012945.5, 'double'],
[PHP_INT_MAX, PHP_INT_MAX, 'integer'],
[~PHP_INT_MAX + 1, ~PHP_INT_MAX + 1, 'integer'], // ~PHP_INT_MAX === PHP_INT_MIN, PHP_INT_MIN being PHP7+
[PHP_INT_MAX + 1, PHP_INT_MAX + 1, 'double'],
];
}
/**
* @dataProvider dataProviderForTestFormatNumericCellValueWithNumbers
*
* @param int|float|string $value
* @param int|float $expectedFormattedValue
* @param string $expectedType
* @return void
*/
public function testFormatNumericCellValueWithNumbers($value, $expectedFormattedValue, $expectedType)
{
/** @var StyleManager|\PHPUnit_Framework_MockObject_MockObject $styleManagerMock */
$styleManagerMock = $this->createMock(StyleManager::class);
$styleManagerMock
->expects($this->once())
->method('shouldFormatNumericValueAsDate')
->will($this->returnValue(false));
$formatter = new CellValueFormatter(null, $styleManagerMock, false, false, new Escaper\XLSX());
$formattedValue = \ReflectionHelper::callMethodOnObject($formatter, 'formatNumericCellValue', $value, 0);
$this->assertEquals($expectedFormattedValue, $formattedValue);
$this->assertEquals($expectedType, gettype($formattedValue));
}
/**
* @return array
*/
public function dataProviderForTestFormatStringCellValue()
{
return [
['A', 'A'],
[' A ', ' A '],
["\n\tA\n\t", "\n\tA\n\t"],
[' ', ' '],
];
}
/**
* @dataProvider dataProviderForTestFormatStringCellValue
*
* @param string $value
* @param string $expectedFormattedValue
* @return void
*/
public function testFormatInlineStringCellValue($value, $expectedFormattedValue)
{
$nodeListMock = $this->createMock(\DOMNodeList::class);
$nodeListMock
->expects($this->atLeastOnce())
->method('item')
->with(0)
->will($this->returnValue((object) ['nodeValue' => $value]));
$nodeMock = $this->createMock(\DOMElement::class);
$nodeMock
->expects($this->atLeastOnce())
->method('getElementsByTagName')
->with(CellValueFormatter::XML_NODE_INLINE_STRING_VALUE)
->will($this->returnValue($nodeListMock));
$formatter = new CellValueFormatter(null, null, false, false, new Escaper\XLSX());
$formattedValue = \ReflectionHelper::callMethodOnObject($formatter, 'formatInlineStringCellValue', $nodeMock);
$this->assertEquals($expectedFormattedValue, $formattedValue);
}
}