|
35 | 35 | use OCP\IUserManager; |
36 | 36 | use OCP\IUserSession; |
37 | 37 | use OCP\Mail\IMailer; |
| 38 | +use PhpOffice\PhpSpreadsheet\Cell\DataType; |
| 39 | +use PhpOffice\PhpSpreadsheet\Spreadsheet; |
38 | 40 | use PHPUnit\Framework\MockObject\MockObject; |
39 | 41 | use Psr\Log\LoggerInterface; |
40 | 42 | use Test\TestCase; |
@@ -618,6 +620,53 @@ public function testGetSubmissionsDataThrowsExceptionOnInvalidFormat() { |
618 | 620 | $this->submissionService->getSubmissionsData($form, 'invalid'); |
619 | 621 | } |
620 | 622 |
|
| 623 | + public static function dataSetCellValueType(): array { |
| 624 | + return [ |
| 625 | + // Radio (and similar choice) answers are always strings, even when the option |
| 626 | + // labels are pure numbers. For spreadsheet formats they must be stored as numbers |
| 627 | + // so they can be aggregated (e.g. averaged) in the spreadsheet application. |
| 628 | + 'radio-numeric-label-xlsx' => ['xlsx', '3', DataType::TYPE_NUMERIC, 3], |
| 629 | + 'radio-numeric-label-ods' => ['ods', '5', DataType::TYPE_NUMERIC, 5], |
| 630 | + 'numeric-zero' => ['xlsx', '0', DataType::TYPE_NUMERIC, 0], |
| 631 | + 'numeric-decimal' => ['xlsx', '3.5', DataType::TYPE_NUMERIC, 3.5], |
| 632 | + // Values starting with a formula-trigger character keep the string typing so they |
| 633 | + // are never interpreted as formulas. |
| 634 | + 'formula' => ['xlsx', '=SUM(A1:A2)', DataType::TYPE_STRING, '=SUM(A1:A2)'], |
| 635 | + 'negative-number' => ['xlsx', '-5', DataType::TYPE_STRING, '-5'], |
| 636 | + 'plus-prefixed' => ['xlsx', '+5', DataType::TYPE_STRING, '+5'], |
| 637 | + 'at-prefixed' => ['xlsx', '@foo', DataType::TYPE_STRING, '@foo'], |
| 638 | + // Strings whose canonical numeric form would differ must stay text to avoid data |
| 639 | + // loss (leading-zero phone numbers, scientific notation, trailing decimal zeros, …). |
| 640 | + 'leading-zero' => ['xlsx', '0123456789', DataType::TYPE_STRING, '0123456789'], |
| 641 | + 'scientific' => ['xlsx', '1e5', DataType::TYPE_STRING, '1e5'], |
| 642 | + 'trailing-decimal-zero' => ['xlsx', '3.50', DataType::TYPE_STRING, '3.50'], |
| 643 | + 'text' => ['xlsx', 'Option A', DataType::TYPE_STRING, 'Option A'], |
| 644 | + // CSV is always escaped and kept as string, even for pure numbers. |
| 645 | + 'csv-number' => ['csv', '3', DataType::TYPE_STRING, '3'], |
| 646 | + 'csv-formula' => ['csv', '=danger', DataType::TYPE_STRING, "'=danger"], |
| 647 | + ]; |
| 648 | + } |
| 649 | + |
| 650 | + /** |
| 651 | + * @dataProvider dataSetCellValueType |
| 652 | + */ |
| 653 | + public function testSetCellValueDataType(string $fileFormat, string $value, string $expectedType, mixed $expectedValue): void { |
| 654 | + $spreadsheet = new Spreadsheet(); |
| 655 | + $worksheet = $spreadsheet->getActiveSheet(); |
| 656 | + |
| 657 | + TestCase::invokePrivate($this->submissionService, 'setCellValue', [$worksheet, 1, 1, $value, $fileFormat]); |
| 658 | + |
| 659 | + $cell = $worksheet->getCell([1, 1]); |
| 660 | + |
| 661 | + $this->assertSame($expectedType, $cell->getDataType()); |
| 662 | + if ($expectedType === DataType::TYPE_NUMERIC) { |
| 663 | + $this->assertEquals($expectedValue, $cell->getValue()); |
| 664 | + } else { |
| 665 | + // assertSame guards against a numeric-looking string being silently coerced. |
| 666 | + $this->assertSame($expectedValue, $cell->getValue()); |
| 667 | + } |
| 668 | + } |
| 669 | + |
621 | 670 | /** |
622 | 671 | * Setting up a very simple default CsvTest |
623 | 672 | */ |
|
0 commit comments