Cleanup 3 LookupRef Tests (#3097)

Scrutinizer had previously suggested annotations for 3 LookupRef tests, but it no longer accepts its own annotation for those cases. This PR cleans them up. ColumnsTest and RowsTest are extremely straightforward.

IndexTest is a bit more complicated, but only because, unlike the other two, it had no test which executed in the context of a spreadsheet. And, when I added those, I discovered a couple of bugs. INDEX always requires at least 2 parameters (row# is always required), but its entry in the function table specified 1-4 parameters, now changed to 2-4. And, omitting col# is not handled the same way as specifying 0 for col#, though the code had treated them identically. (The same would have been true for row# but, because it is now required, ...)
This commit is contained in:
oleibman 2022-10-01 07:05:54 -07:00 committed by GitHub
parent 35b42cc180
commit d27b6a672a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 297 additions and 9 deletions

View File

@ -1450,7 +1450,7 @@ class Calculation
'INDEX' => [
'category' => Category::CATEGORY_LOOKUP_AND_REFERENCE,
'functionCall' => [LookupRef\Matrix::class, 'index'],
'argumentCount' => '1-4',
'argumentCount' => '2-4',
],
'INDIRECT' => [
'category' => Category::CATEGORY_LOOKUP_AND_REFERENCE,

View File

@ -76,13 +76,14 @@ class Matrix
* If an array of values is passed as the $rowNum and/or $columnNum arguments, then the returned result
* will also be an array with the same dimensions
*/
public static function index($matrix, $rowNum = 0, $columnNum = 0)
public static function index($matrix, $rowNum = 0, $columnNum = null)
{
if (is_array($rowNum) || is_array($columnNum)) {
return self::evaluateArrayArgumentsSubsetFrom([self::class, __FUNCTION__], 1, $matrix, $rowNum, $columnNum);
}
$rowNum = $rowNum ?? 0;
$originalColumnNum = $columnNum;
$columnNum = $columnNum ?? 0;
try {
@ -102,6 +103,9 @@ class Matrix
if ($columnNum > count($columnKeys)) {
return ExcelError::REF();
}
if ($originalColumnNum === null && 1 < count($columnKeys)) {
return ExcelError::REF();
}
if ($columnNum === 0) {
return self::extractRowValue($matrix, $rowKeys, $rowNum);

View File

@ -12,10 +12,11 @@ class ColumnsTest extends TestCase
* @dataProvider providerCOLUMNS
*
* @param mixed $expectedResult
* @param null|array|string $arg
*/
public function testCOLUMNS($expectedResult, ...$args): void
public function testCOLUMNS($expectedResult, $arg): void
{
$result = LookupRef::COLUMNS(/** @scrutinizer ignore-type */ ...$args);
$result = LookupRef::COLUMNS($arg);
self::assertEquals($expectedResult, $result);
}

View File

@ -0,0 +1,39 @@
<?php
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
class IndexOnSpreadsheetTest extends AllSetupTeardown
{
/**
* @dataProvider providerINDEXonSpreadsheet
*
* @param mixed $expectedResult
* @param null|int|string $rowNum
* @param null|int|string $colNum
*/
public function testIndexOnSpreadsheet($expectedResult, array $matrix, $rowNum = null, $colNum = null): void
{
$this->mightHaveException($expectedResult);
$sheet = $this->getSheet();
$sheet->fromArray($matrix);
$maxRow = $sheet->getHighestRow();
$maxColumn = $sheet->getHighestColumn();
$formulaArray = "A1:$maxColumn$maxRow";
if ($rowNum === null) {
$formula = "=INDEX($formulaArray)";
} elseif ($colNum === null) {
$formula = "=INDEX($formulaArray, $rowNum)";
} else {
$formula = "=INDEX($formulaArray, $rowNum, $colNum)";
}
$sheet->getCell('ZZ98')->setValue('x');
$sheet->getCell('ZZ99')->setValue($formula);
$result = $sheet->getCell('ZZ99')->getCalculatedValue();
self::assertEquals($expectedResult, $result);
}
public function providerINDEXonSpreadsheet(): array
{
return require 'tests/data/Calculation/LookupRef/INDEXonSpreadsheet.php';
}
}

View File

@ -3,7 +3,7 @@
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
use PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Matrix;
use PHPUnit\Framework\TestCase;
class IndexTest extends TestCase
@ -12,10 +12,19 @@ class IndexTest extends TestCase
* @dataProvider providerINDEX
*
* @param mixed $expectedResult
* @param mixed $matrix
* @param mixed $rowNum
* @param mixed $colNum
*/
public function testINDEX($expectedResult, ...$args): void
public function testINDEX($expectedResult, $matrix, $rowNum = null, $colNum = null): void
{
$result = LookupRef::INDEX(/** @scrutinizer ignore-type */ ...$args);
if ($rowNum === null) {
$result = Matrix::index($matrix);
} elseif ($colNum === null) {
$result = Matrix::index($matrix, $rowNum);
} else {
$result = Matrix::index($matrix, $rowNum, $colNum);
}
self::assertEquals($expectedResult, $result);
}

View File

@ -12,10 +12,11 @@ class RowsTest extends TestCase
* @dataProvider providerROWS
*
* @param mixed $expectedResult
* @param null|array|string $arg
*/
public function testROWS($expectedResult, ...$args): void
public function testROWS($expectedResult, $arg): void
{
$result = LookupRef::ROWS(/** @scrutinizer ignore-type */ ...$args);
$result = LookupRef::ROWS($arg);
self::assertEquals($expectedResult, $result);
}

View File

@ -0,0 +1,234 @@
<?php
return [
'Single Cell' => [
1, // Expected
[
[1],
],
0,
],
'Row Number omitted' => [
'exception', // Expected
[
[1],
],
],
'Negative Row' => [
'#VALUE!', // Expected
[
[1],
[2],
],
-1,
],
'Row > matrix rows' => [
'#REF!', // Expected
[
[1],
[2],
],
10,
],
'Row is not a number' => [
'#NAME?', // Expected
[
[1],
[2],
],
'NaN',
],
'Row is reference to non-number' => [
'#VALUE!', // Expected
[
[1],
[2],
],
'ZZ98',
],
'Row is quoted non-numeric result' => [
'#VALUE!', // Expected
[
[1],
[2],
],
'"string"',
],
'Row is Error' => [
'#N/A', // Expected
[
[1],
[2],
],
'#N/A',
],
'Return row 2 only one column' => [
'xyz', // Expected
[
['abc'],
['xyz'],
],
2,
],
'Return row 1 col 2' => [
'def', // Expected
[
['abc', 'def'],
['xyz', 'tuv'],
],
1,
2,
],
'Column number omitted from 2-column matrix' => [
'#REF!', // Expected
[
['abc', 'def'],
['xyz', 'tuv'],
],
1,
],
'Column number omitted from 1-column matrix' => [
'xyz', // Expected
[
['abc'],
['xyz'],
],
2,
],
'Return row 2 from larger matrix (Phpspreadsheet flattens expected [2,4] to single value)' => [
2, // Expected
// Input
[
[1, 3],
[2, 4],
],
2,
0,
],
'Negative Column' => [
'#VALUE!', // Expected
[
[1, 3],
[2, 4],
],
0,
-1,
],
'Column > matrix columns' => [
'#REF!', // Expected
[
[1, 3],
[2, 4],
],
2,
10,
],
'Column is not a number' => [
'#NAME?', // Expected
[
[1],
[2],
],
1,
'NaN',
],
'Column is reference to non-number' => [
'#VALUE!', // Expected
[
[1],
[2],
],
1,
'ZZ98',
],
'Column is quoted non-number' => [
'#VALUE!', // Expected
[
[1],
[2],
],
1,
'"string"',
],
'Column is Error' => [
'#N/A', // Expected
[
[1],
[2],
],
1,
'#N/A',
],
'Row 2 Column 2' => [
4, // Expected
[
[1, 3],
[2, 4],
],
2,
2,
],
'Row 2 Column 2 Alphabetic' => [
'Pears',
[
['Apples', 'Lemons'],
['Bananas', 'Pears'],
],
2,
2,
],
'Row 2 Column 1 Alphabetic' => [
'Bananas',
[
['Apples', 'Lemons'],
['Bananas', 'Pears'],
],
2,
1,
],
'Row 2 Column 0 (PhpSpreadsheet flattens result)' => [
'Bananas',
[
['Apples', 'Lemons'],
['Bananas', 'Pears'],
],
2,
0,
],
'Row 5 column 2' => [
3,
[
[4, 6],
[5, 3],
[6, 9],
[7, 5],
[8, 3],
],
5,
2,
],
'Row 5 column 0 (flattened)' => [
8,
[
[4, 6],
[5, 3],
[6, 9],
[7, 5],
[8, 3],
],
5,
0,
],
'Row 0 column 2 (flattened)' => [
6,
[
[4, 6],
[5, 3],
[6, 9],
[7, 5],
[8, 3],
],
0,
2,
],
];