From 3ae5a3fae397973c5d81c1250a8fd2d5896653eb Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Fri, 1 Apr 2022 16:55:58 +0200 Subject: [PATCH] Additional unit tests for BColumnAndRow methods, to verify that they still work as expected --- phpstan-baseline.neon | 5 - src/PhpSpreadsheet/Worksheet/Worksheet.php | 211 ++++++++++++------ .../Worksheet/ByColumnAndRowTest.php | 188 ++++++++++++++++ 3 files changed, 335 insertions(+), 69 deletions(-) create mode 100644 tests/PhpSpreadsheetTests/Worksheet/ByColumnAndRowTest.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 9ecc0f01..278efd69 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -4345,11 +4345,6 @@ parameters: count: 1 path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - - message: "#^Result of && is always true\\.$#" - count: 1 - path: src/PhpSpreadsheet/Worksheet/Worksheet.php - - message: "#^Right side of && is always true\\.$#" count: 1 diff --git a/src/PhpSpreadsheet/Worksheet/Worksheet.php b/src/PhpSpreadsheet/Worksheet/Worksheet.php index 54fcc0de..2f8f6972 100644 --- a/src/PhpSpreadsheet/Worksheet/Worksheet.php +++ b/src/PhpSpreadsheet/Worksheet/Worksheet.php @@ -4,6 +4,8 @@ namespace PhpOffice\PhpSpreadsheet\Worksheet; use ArrayObject; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; +use PhpOffice\PhpSpreadsheet\Calculation\Functions; +use PhpOffice\PhpSpreadsheet\Cell\AddressRange; use PhpOffice\PhpSpreadsheet\Cell\Cell; use PhpOffice\PhpSpreadsheet\Cell\CellAddress; use PhpOffice\PhpSpreadsheet\Cell\CellRange; @@ -1118,6 +1120,9 @@ class Worksheet implements IComparable return null; } [$worksheet, $address] = self::extractSheetTitle($cellAddress, true); +// if (!empty($worksheet) && $worksheet !== $this->getTitle()) { +// throw new Exception('Reference is not for this worksheet'); +// } return empty($worksheet) ? strtoupper($address) : $worksheet . '!' . strtoupper($address); } @@ -1129,6 +1134,50 @@ class Worksheet implements IComparable return (string) $cellAddress; } + /** + * Validate a cell range. + * + * @param AddressRange|array|CellAddress|string $cellRange Coordinate of the cells as a string, eg: 'C5:F12'; + * or as an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 12]), + * or as a CellAddress or AddressRange object. + */ + protected function validateCellOrCellRange($cellRange): string + { + if (is_object($cellRange) && $cellRange instanceof CellAddress) { + $cellRange = new CellRange($cellRange, $cellRange); + } + + return $this->validateCellRange($cellRange); + } + + /** + * Validate a cell range. + * + * @param AddressRange|array|string $cellRange Coordinate of the cells as a string, eg: 'C5:F12'; + * or as an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 12]), + * or as an AddressRange object. + */ + protected function validateCellRange($cellRange): string + { + if (is_string($cellRange)) { + [$worksheet, $addressRange] = self::extractSheetTitle($cellRange, true); + + // Convert 'A:C' to 'A1:C1048576' + $addressRange = self::pregReplace('/^([A-Z]+):([A-Z]+)$/', '${1}1:${2}1048576', $addressRange); + // Convert '1:3' to 'A1:XFD3' + $addressRange = self::pregReplace('/^(\\d+):(\\d+)$/', 'A${1}:XFD${2}', $addressRange); + + return empty($worksheet) ? strtoupper($addressRange) : $worksheet . '!' . strtoupper($addressRange); + } + + if (is_array($cellRange)) { + [$from, $to] = array_chunk($cellRange, 2); + $cellRange = new CellRange(CellAddress::fromColumnRowArray($from), CellAddress::fromColumnRowArray($to)); + } + + return (string) $cellRange; + } + /** * Set a cell value. * @@ -1455,10 +1504,15 @@ class Worksheet implements IComparable /** * Get style for cell. * - * @param string $cellCoordinate Cell coordinate (or range) to get style for, eg: 'A1' + * @param AddressRange|array|CellAddress|string $cellCoordinate + * A simple string containing a cell address like 'A1' or a cell range like 'A1:E10' + * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), + * or a CellAddress or AddressRange object. */ public function getStyle($cellCoordinate): Style { + $cellCoordinate = $this->validateCellRange($cellCoordinate); + // set this sheet as active $this->parent->setActiveSheetIndex($this->parent->getIndex($this)); @@ -1468,6 +1522,35 @@ class Worksheet implements IComparable return $this->parent->getCellXfSupervisor(); } + /** + * Get style for cell by using numeric cell coordinates. + * + * @Deprecated 1.23.0 + * Use the getStyle() method with a cell address range such as 'C5:F8' instead;, + * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), + * or an AddressRange object. + * + * @param int $columnIndex1 Numeric column coordinate of the cell + * @param int $row1 Numeric row coordinate of the cell + * @param null|int $columnIndex2 Numeric column coordinate of the range cell + * @param null|int $row2 Numeric row coordinate of the range cell + * + * @return Style + */ + public function getStyleByColumnAndRow($columnIndex1, $row1, $columnIndex2 = null, $row2 = null) + { + if ($columnIndex2 !== null && $row2 !== null) { + $cellRange = new CellRange( + CellAddress::fromColumnAndRow($columnIndex1, $row1), + CellAddress::fromColumnAndRow($columnIndex2, $row2) + ); + + return $this->getStyle($cellRange); + } + + return $this->getStyle(CellAddress::fromColumnAndRow($columnIndex1, $row1)); + } + /** * Get conditional styles for a cell. * @@ -1522,7 +1605,7 @@ class Worksheet implements IComparable { $coordinate = strtoupper($coordinate); if (strpos($coordinate, ':') !== false) { - return isset($this->conditionalStylesCollection[strtoupper($coordinate)]); + return isset($this->conditionalStylesCollection[$coordinate]); } $cell = $this->getCell($coordinate); @@ -1574,30 +1657,6 @@ class Worksheet implements IComparable return $this; } - /** - * Get style for cell by using numeric cell coordinates. - * - * @param int $columnIndex1 Numeric column coordinate of the cell - * @param int $row1 Numeric row coordinate of the cell - * @param null|int $columnIndex2 Numeric column coordinate of the range cell - * @param null|int $row2 Numeric row coordinate of the range cell - * - * @return Style - */ - public function getStyleByColumnAndRow($columnIndex1, $row1, $columnIndex2 = null, $row2 = null) - { - if ($columnIndex2 !== null && $row2 !== null) { - $cellRange = new CellRange( - CellAddress::fromColumnAndRow($columnIndex1, $row1), - CellAddress::fromColumnAndRow($columnIndex2, $row2) - ); - - return $this->getStyle($cellRange); - } - - return $this->getStyle(CellAddress::fromColumnAndRow($columnIndex1, $row1)); - } - /** * Duplicate cell style to a range of cells. * @@ -1690,11 +1749,7 @@ class Worksheet implements IComparable */ public function setBreak($coordinate, $break) { - $cellAddress = $this->validateCellAddress($coordinate); - - if ($cellAddress === '') { - throw new Exception('No cell coordinate specified.'); - } + $cellAddress = Functions::trimSheetFromCellReference($this->validateCellAddress($coordinate) ?? ''); if ($break === self::BREAK_NONE) { if (isset($this->breaks[$cellAddress])) { @@ -1738,18 +1793,15 @@ class Worksheet implements IComparable /** * Set merge on a cell range. * - * @param string $range Cell range (e.g. A1:E1) + * @param AddressRange|array|string $range A simple string containing a Cell range like 'A1:E10' + * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), + * or an AddressRange. * * @return $this */ public function mergeCells($range) { - // Uppercase coordinate - $range = strtoupper($range); - // Convert 'A:C' to 'A1:C1048576' - $range = self::pregReplace('/^([A-Z]+):([A-Z]+)$/', '${1}1:${2}1048576', $range); - // Convert '1:3' to 'A1:XFD3' - $range = self::pregReplace('/^(\\d+):(\\d+)$/', 'A${1}:XFD${2}', $range); + $range = Functions::trimSheetFromCellReference($this->validateCellRange($range)); if (preg_match('/^([A-Z]+)(\\d+):([A-Z]+)(\\d+)$/', $range, $matches) === 1) { $this->mergeCells[$range] = $range; @@ -1763,7 +1815,7 @@ class Worksheet implements IComparable $numberColumns = $lastColumnIndex - $firstColumnIndex; // create upper left cell if it does not already exist - $upperLeft = "$firstColumn$firstRow"; + $upperLeft = "{$firstColumn}{$firstRow}"; if (!$this->cellExists($upperLeft)) { $this->getCell($upperLeft)->setValueExplicit(null, DataType::TYPE_NULL); } @@ -1826,9 +1878,9 @@ class Worksheet implements IComparable * Set merge on a cell range by using numeric cell coordinates. * * @Deprecated 1.23.0 - * Use the mergeCells() method with a cell address range such as 'C5:E8' instead;, - * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5]), - * or a CellAddress object. + * Use the mergeCells() method with a cell address range such as 'C5:F8' instead;, + * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), + * or an AddressRange object. * * @param int $columnIndex1 Numeric column coordinate of the first cell * @param int $row1 Numeric row coordinate of the first cell @@ -1850,14 +1902,15 @@ class Worksheet implements IComparable /** * Remove merge on a cell range. * - * @param string $range Cell range (e.g. A1:E1) + * @param AddressRange|array|string $range A simple string containing a Cell range like 'A1:E10' + * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), + * or an AddressRange. * * @return $this */ public function unmergeCells($range) { - // Uppercase coordinate - $range = strtoupper($range); + $range = Functions::trimSheetFromCellReference($this->validateCellRange($range)); if (strpos($range, ':') !== false) { if (isset($this->mergeCells[$range])) { @@ -1875,6 +1928,11 @@ class Worksheet implements IComparable /** * Remove merge on a cell range by using numeric cell coordinates. * + * @Deprecated 1.23.0 + * Use the unmergeCells() method with a cell address range such as 'C5:F8' instead;, + * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), + * or an AddressRange object. + * * @param int $columnIndex1 Numeric column coordinate of the first cell * @param int $row1 Numeric row coordinate of the first cell * @param int $columnIndex2 Numeric column coordinate of the last cell @@ -1918,9 +1976,11 @@ class Worksheet implements IComparable } /** - * Set protection on a cell range. + * Set protection on a cell or cell range. * - * @param string $range Cell (e.g. A1) or cell range (e.g. A1:E1) + * @param AddressRange|array|CellAddress|string $range A simple string containing a Cell range like 'A1:E10' + * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), + * or a CellAddress or AddressRange object. * @param string $password Password to unlock the protection * @param bool $alreadyHashed If the password has already been hashed, set this to true * @@ -1928,8 +1988,7 @@ class Worksheet implements IComparable */ public function protectCells($range, $password, $alreadyHashed = false) { - // Uppercase coordinate - $range = strtoupper($range); + $range = Functions::trimSheetFromCellReference($this->validateCellRange($range)); if (!$alreadyHashed) { $password = Shared\PasswordHasher::hashPassword($password); @@ -1942,6 +2001,11 @@ class Worksheet implements IComparable /** * Set protection on a cell range by using numeric cell coordinates. * + * @Deprecated 1.23.0 + * Use the protectCells() method with a cell address range such as 'C5:F8' instead;, + * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), + * or an AddressRange object. + * * @param int $columnIndex1 Numeric column coordinate of the first cell * @param int $row1 Numeric row coordinate of the first cell * @param int $columnIndex2 Numeric column coordinate of the last cell @@ -1962,16 +2026,17 @@ class Worksheet implements IComparable } /** - * Remove protection on a cell range. + * Remove protection on a cell or cell range. * - * @param string $range Cell (e.g. A1) or cell range (e.g. A1:E1) + * @param AddressRange|array|CellAddress|string $range A simple string containing a Cell range like 'A1:E10' + * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), + * or a CellAddress or AddressRange object. * * @return $this */ public function unprotectCells($range) { - // Uppercase coordinate - $range = strtoupper($range); + $range = Functions::trimSheetFromCellReference($this->validateCellRange($range)); if (isset($this->protectedCells[$range])) { unset($this->protectedCells[$range]); @@ -1985,6 +2050,11 @@ class Worksheet implements IComparable /** * Remove protection on a cell range by using numeric cell coordinates. * + * @Deprecated 1.23.0 + * Use the protectCells() method with a cell address range such as 'C5:F8' instead;, + * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), + * or an AddressRange object. + * * @param int $columnIndex1 Numeric column coordinate of the first cell * @param int $row1 Numeric row coordinate of the first cell * @param int $columnIndex2 Numeric column coordinate of the last cell @@ -2025,17 +2095,21 @@ class Worksheet implements IComparable /** * Set AutoFilter. * - * @param AutoFilter|string $autoFilterOrRange + * @param AddressRange|array|AutoFilter|string $autoFilterOrRange * A simple string containing a Cell range like 'A1:E10' is permitted for backward compatibility + * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), + * or an AddressRange. * * @return $this */ public function setAutoFilter($autoFilterOrRange) { - if (is_string($autoFilterOrRange)) { - $this->autoFilter->setRange($autoFilterOrRange); - } elseif (is_object($autoFilterOrRange) && ($autoFilterOrRange instanceof AutoFilter)) { + if (is_object($autoFilterOrRange) && ($autoFilterOrRange instanceof AutoFilter)) { $this->autoFilter = $autoFilterOrRange; + } else { + $cellRange = Functions::trimSheetFromCellReference($this->validateCellRange($autoFilterOrRange)); + + $this->autoFilter->setRange($cellRange); } return $this; @@ -2044,6 +2118,11 @@ class Worksheet implements IComparable /** * Set Autofilter Range by using numeric cell coordinates. * + * @Deprecated 1.23.0 + * Use the setAutoFilter() method with a cell address range such as 'C5:F8' instead;, + * or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]), + * or an AddressRange object or AutoFilter object. + * * @param int $columnIndex1 Numeric column coordinate of the first cell * @param int $row1 Numeric row coordinate of the first cell * @param int $columnIndex2 Numeric column coordinate of the second cell @@ -2053,11 +2132,12 @@ class Worksheet implements IComparable */ public function setAutoFilterByColumnAndRow($columnIndex1, $row1, $columnIndex2, $row2) { - return $this->setAutoFilter( - Coordinate::stringFromColumnIndex($columnIndex1) . $row1 - . ':' . - Coordinate::stringFromColumnIndex($columnIndex2) . $row2 + $cellRange = new CellRange( + CellAddress::fromColumnAndRow($columnIndex1, $row1), + CellAddress::fromColumnAndRow($columnIndex2, $row2) ); + + return $this->setAutoFilter($cellRange); } /** @@ -2090,9 +2170,11 @@ class Worksheet implements IComparable * - B2 will freeze the rows above and to the left of cell B2 (i.e row 1 and column A) * * @param null|array|CellAddress|string $coordinate Coordinate of the cell as a string, eg: 'C5'; - * or as an array of [$columnIndex, $row] (e.g. [3, 5]), or a CellAddress object. - * Passing a null value for this argument will clear an existing freeze pane for this worksheet. - * @param null|string $topLeftCell default position of the right bottom pane + * or as an array of [$columnIndex, $row] (e.g. [3, 5]), or a CellAddress object. + * Passing a null value for this argument will clear any existing freeze pane for this worksheet. + * @param null|array|CellAddress|string $topLeftCell default position of the right bottom pane + * Coordinate of the cell as a string, eg: 'C5'; or as an array of [$columnIndex, $row] (e.g. [3, 5]), + * or a CellAddress object. * * @return $this */ @@ -2102,6 +2184,7 @@ class Worksheet implements IComparable if (is_string($cellAddress) && Coordinate::coordinateIsRange($cellAddress)) { throw new Exception('Freeze pane can not be set on a range of cells.'); } + $topLeftCell = $this->validateCellAddress($topLeftCell, true); if ($cellAddress !== null && $topLeftCell === null) { $coordinate = Coordinate::coordinateFromString($cellAddress); diff --git a/tests/PhpSpreadsheetTests/Worksheet/ByColumnAndRowTest.php b/tests/PhpSpreadsheetTests/Worksheet/ByColumnAndRowTest.php new file mode 100644 index 00000000..d38be252 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Worksheet/ByColumnAndRowTest.php @@ -0,0 +1,188 @@ +getActiveSheet(); + + $sheet->setCellValueByColumnAndRow(2, 2, 2); + self::assertSame(2, $sheet->getCell('B2')->getValue()); + } + + public function testSetCellValueExplicitByColumnAndRow(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $sheet->setCellValueExplicitByColumnAndRow(2, 2, '="PHP Rules"', DataType::TYPE_STRING); + self::assertSame('="PHP Rules"', $sheet->getCell('B2')->getValue()); + self::assertSame(DataType::TYPE_STRING, $sheet->getCell('B2')->getDataType()); + } + + public function testCellExistsByColumnAndRow(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $cellExists = $sheet->cellExistsByColumnAndRow(2, 2); + self::assertFalse($cellExists); + + $sheet->setCellValue('B2', 2); + + $cellExists = $sheet->cellExistsByColumnAndRow(2, 2); + self::assertTrue($cellExists); + } + + public function testGetCellByColumnAndRow(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $sheet->setCellValue('B2', 2); + $cell = $sheet->getCellByColumnAndRow(2, 2); + self::assertSame('B2', $cell->getCoordinate()); + self::assertSame(2, $cell->getValue()); + } + + public function testGetStyleByColumnAndRow(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $data = [['A', 'B'], ['C', 'D']]; + $sheet->fromArray($data, null, 'B2', true); + $sheet->getStyle('B2:C3')->getFont()->setBold(true); + + $rangeStyle = $sheet->getStyleByColumnAndRow(2, 2, 3, 3); + self::assertTrue($rangeStyle->getFont()->getBold()); + + $cellStyle = $sheet->getStyleByColumnAndRow(2, 2); + self::assertTrue($cellStyle->getFont()->getBold()); + } + + public function testSetBreakByColumnAndRow(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $sheet->setCellValue('B2', 2); + $sheet->setBreakByColumnAndRow(2, 2, Worksheet::BREAK_COLUMN); + + $breaks = $sheet->getBreaks(); + self::assertArrayHasKey('B2', $breaks); + self::assertSame(Worksheet::BREAK_COLUMN, $breaks['B2']); + } + + public function testMergeCellsByColumnAndRow(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $data = [['A', 'B'], ['C', 'D']]; + $sheet->fromArray($data, null, 'B2', true); + + $sheet->mergeCellsByColumnAndRow(2, 2, 3, 3); + $mergeRanges = $sheet->getMergeCells(); + self::assertArrayHasKey('B2:C3', $mergeRanges); + } + + public function testUnergeCellsByColumnAndRow(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $data = [['A', 'B'], ['C', 'D']]; + $sheet->fromArray($data, null, 'B2', true); + + $sheet->mergeCells('B2:C3'); + $mergeRanges = $sheet->getMergeCells(); + self::assertArrayHasKey('B2:C3', $mergeRanges); + + $sheet->unmergeCellsByColumnAndRow(2, 2, 3, 3); + $mergeRanges = $sheet->getMergeCells(); + self::assertEmpty($mergeRanges); + } + + public function testProtectCellsByColumnAndRow(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $data = [['A', 'B'], ['C', 'D']]; + $sheet->fromArray($data, null, 'B2', true); + + $sheet->protectCellsByColumnAndRow(2, 2, 3, 3, 'secret', false); + $protectedRanges = $sheet->getProtectedCells(); + self::assertArrayHasKey('B2:C3', $protectedRanges); + } + + public function testUnprotectCellsByColumnAndRow(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $data = [['A', 'B'], ['C', 'D']]; + $sheet->fromArray($data, null, 'B2', true); + + $sheet->protectCells('B2:C3', 'secret', false); + $protectedRanges = $sheet->getProtectedCells(); + self::assertArrayHasKey('B2:C3', $protectedRanges); + + $sheet->unprotectCellsByColumnAndRow(2, 2, 3, 3); + $protectedRanges = $sheet->getProtectedCells(); + self::assertEmpty($protectedRanges); + } + + public function testSetAutoFilterByColumnAndRow(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $data = [['A', 'B'], ['C', 'D']]; + $sheet->fromArray($data, null, 'B2', true); + + $sheet->setAutoFilterByColumnAndRow(2, 2, 3, 3); + $autoFilter = $sheet->getAutoFilter(); + self::assertInstanceOf(AutoFilter::class, $autoFilter); + self::assertSame('B2:C3', $autoFilter->getRange()); + } + + public function testFreezePaneByColumnAndRow(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $data = [['A', 'B'], ['C', 'D']]; + $sheet->fromArray($data, null, 'B2', true); + + $sheet->freezePaneByColumnAndRow(2, 2); + $freezePane = $sheet->getFreezePane(); + self::assertSame('B2', $freezePane); + } + + public function testGetCommentByColumnAndRow(): void + { + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + $sheet->setCellValue('B2', 2); + $spreadsheet->getActiveSheet() + ->getComment('B2') + ->getText()->createTextRun('My Test Comment'); + + $comment = $sheet->getCommentByColumnAndRow(2, 2); + self::assertInstanceOf(Comment::class, $comment); + self::assertSame('My Test Comment', $comment->getText()->getPlainText()); + } +}