Restore Tests Whose Absence Led to Omitted Coverage

This commit is contained in:
oleibman
2026-01-16 18:21:57 -08:00
parent 820640d516
commit 860f2c6637
3 changed files with 121 additions and 53 deletions
@@ -34,4 +34,10 @@ final class CalculationParserOnly extends Calculation
return self::$parserInstance;
}
/** @param mixed $enabled Unused, property will always be false in this class */
public function setBranchPruningEnabled(mixed $enabled): self
{
return $this;
}
}
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\CalculationParserOnly;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
@@ -424,4 +425,27 @@ class CalculationTest extends TestCase
{
return require 'tests/data/Calculation/Calculation.php';
}
public function testBranchPruningFlag(): void
{
$calc1 = Calculation::getInstance();
$calc2 = CalculationParserOnly::getParserInstance();
self::assertNotSame($calc1, $calc2);
$calc1a = Calculation::getInstance();
$calc2a = CalculationParserOnly::getParserInstance();
self::assertSame($calc1, $calc1a);
self::assertSame($calc2, $calc2a);
self::assertFalse($calc2->getBranchPruningEnabled());
$calc2->enableBranchPruning();
self::assertFalse($calc2->getBranchPruningEnabled(), 'no change for ParserOnly');
$calc2->disableBranchPruning();
self::assertFalse($calc2->getBranchPruningEnabled());
self::assertTrue($calc1->getBranchPruningEnabled(), 'parserOnly did not affect Calculation singleton');
$calc1->disableBranchPruning();
self::assertFalse($calc1->getBranchPruningEnabled());
$calc1->enableBranchPruning();
self::assertTrue($calc1->getBranchPruningEnabled());
}
}
@@ -4,9 +4,13 @@ declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests\Cell;
use DateTime;
use DateTimeImmutable;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder;
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Stringable;
@@ -22,8 +26,14 @@ class DefaultValueBinderTest extends TestCase
#[DataProvider('binderProvider')]
public function testBindValue(mixed $value, string $expectedDataType): void
{
$result = DefaultValueBinder::dataTypeForValue($value);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$cell = $sheet->getCell('A1');
$binder = new DefaultValueBinder();
self::assertTrue($binder->bindValue($cell, $value));
$result = $cell->getDataType();
self::assertSame($expectedDataType, $result);
$spreadsheet->disconnectWorksheets();
}
/**
@@ -44,6 +54,10 @@ class DefaultValueBinderTest extends TestCase
'positive integer' => [42, DataType::TYPE_NUMERIC],
'negative integer' => [-100, DataType::TYPE_NUMERIC],
// Very large integers treated as string to prevent precision loss
'large positive' => [1_000_000_000_000_000, DataType::TYPE_STRING],
'large negative' => [-1_000_000_000_000_000, DataType::TYPE_STRING],
// Floats
'float' => [3.14159, DataType::TYPE_NUMERIC],
'negative float' => [-2.5, DataType::TYPE_NUMERIC],
@@ -80,6 +94,18 @@ class DefaultValueBinderTest extends TestCase
'error NAME' => ['#NAME?', DataType::TYPE_ERROR],
'error NUM' => ['#NUM!', DataType::TYPE_ERROR],
'error NA' => ['#N/A', DataType::TYPE_ERROR],
// DateTime strings should be treated as string
'datetime format' => ['2024-01-15 10:30:00', DataType::TYPE_STRING],
'date only' => ['2024-01-15', DataType::TYPE_STRING],
'time only' => ['10:30:00', DataType::TYPE_STRING],
// DateTime objects should be treated as string
'DateTime' => [new DateTime(), DataType::TYPE_STRING],
'DateTimeImmutable' => [new DateTimeImmutable(), DataType::TYPE_STRING],
// Stringable object
'Stringable object' => [new StringableObject(), DataType::TYPE_STRING],
];
}
@@ -88,49 +114,82 @@ class DefaultValueBinderTest extends TestCase
*/
public function testRichTextReturnsTypeInline(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$richText = new RichText();
$richText->createTextRun('Hello World');
$result = DefaultValueBinder::dataTypeForValue($richText);
$cell = $sheet->getCell('A1');
$binder = new DefaultValueBinder();
self::assertTrue($binder->bindValue($cell, $richText));
$result = $cell->getDataType();
self::assertSame(DataType::TYPE_INLINE, $result);
$spreadsheet->disconnectWorksheets();
}
/**
* Test that DateTime string format values are handled correctly.
*/
#[DataProvider('dateTimeStringProvider')]
public function testDateTimeStringReturnsTypeString(string $dateTimeString): void
public function testNonStringableBindValue(): void
{
$result = DefaultValueBinder::dataTypeForValue($dateTimeString);
self::assertSame(DataType::TYPE_STRING, $result);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
try {
$sheet->getCell('A1')->setValue($this);
self::fail('Did not receive expected Exception');
} catch (SpreadsheetException $e) {
self::assertStringContainsString('Unable to bind unstringable', $e->getMessage());
}
$sheet->getCell('A2')->setValue(new StringableObject());
self::assertSame('abc', $sheet->getCell('A2')->getValue());
try {
$sheet->getCell('A3')->setValue(fopen(__FILE__, 'rb'));
self::fail('Did not receive expected Exception');
} catch (SpreadsheetException $e) {
self::assertStringContainsString('Unable to bind unstringable', $e->getMessage());
}
try {
$sheet->getCell('A3')->setValue([]);
self::fail('Did not receive expected Exception');
} catch (SpreadsheetException $e) {
self::assertStringContainsString('Unable to bind unstringable', $e->getMessage());
}
$spreadsheet->disconnectWorksheets();
}
/**
* @return array<string, array{string}>
*/
public static function dateTimeStringProvider(): array
#[DataProvider('providerDataTypeForValue')]
public function testDataTypeForValue(mixed $expectedResult, mixed $value): void
{
return [
'datetime format' => ['2024-01-15 10:30:00'],
'date only' => ['2024-01-15'],
'time only' => ['10:30:00'],
];
$result = DefaultValueBinder::dataTypeForValue($value);
self::assertEquals($expectedResult, $result);
}
/**
* Test Stringable objects are converted and handled as strings.
*/
public function testStringableReturnsTypeString(): void
public static function providerDataTypeForValue(): array
{
$stringable = new class() implements Stringable {
public function __toString(): string
{
return 'Hello from Stringable';
}
};
return require 'tests/data/Cell/DefaultValueBinder.php';
}
$result = DefaultValueBinder::dataTypeForValue($stringable);
self::assertSame(DataType::TYPE_STRING, $result);
public function testDataTypeForValueExceptions(): void
{
try {
self::assertSame('s', DefaultValueBinder::dataTypeForValue(new SpreadsheetException()));
} catch (SpreadsheetException $e) {
self::fail('Should not have failed for stringable');
}
try {
DefaultValueBinder::dataTypeForValue([]);
self::fail('Should have failed for array');
} catch (SpreadsheetException $e) {
self::assertStringContainsString('unusable type array', $e->getMessage());
}
try {
DefaultValueBinder::dataTypeForValue(new DateTime());
self::fail('Should have failed for DateTime');
} catch (SpreadsheetException $e) {
self::assertStringContainsString('unusable type DateTime', $e->getMessage());
}
}
/**
@@ -138,7 +197,7 @@ class DefaultValueBinderTest extends TestCase
*/
public function testStringableFormulaReturnsTypeFormula(): void
{
$stringable = new class() implements Stringable {
$stringable = new class () implements Stringable {
public function __toString(): string
{
return '=SUM(A1:A10)';
@@ -149,27 +208,6 @@ class DefaultValueBinderTest extends TestCase
self::assertSame(DataType::TYPE_FORMULA, $result);
}
/**
* Test very large integers are treated as strings to prevent precision loss.
*/
#[DataProvider('largeIntegerProvider')]
public function testLargeIntegersReturnTypeString(int $value): void
{
$result = DefaultValueBinder::dataTypeForValue($value);
self::assertSame(DataType::TYPE_STRING, $result);
}
/**
* @return array<string, array{int}>
*/
public static function largeIntegerProvider(): array
{
return [
'large positive' => [1_000_000_000_000_000],
'large negative' => [-1_000_000_000_000_000],
];
}
/**
* Test that calling dataTypeForValue multiple times with formulas
* works correctly (verifies singleton reuse doesn't cause issues).