HtmlTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. <?php
  2. namespace PhpOffice\PhpSpreadsheetTests\Reader\Html;
  3. use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
  4. use PhpOffice\PhpSpreadsheet\Reader\Html;
  5. use PhpOffice\PhpSpreadsheet\Style\Alignment;
  6. use PhpOffice\PhpSpreadsheet\Style\Border;
  7. use PhpOffice\PhpSpreadsheet\Style\Font;
  8. use PHPUnit\Framework\TestCase;
  9. class HtmlTest extends TestCase
  10. {
  11. public function testCsvWithAngleBracket(): void
  12. {
  13. $filename = 'tests/data/Reader/HTML/csv_with_angle_bracket.csv';
  14. $reader = new Html();
  15. self::assertFalse($reader->canRead($filename));
  16. }
  17. public function testBadHtml(): void
  18. {
  19. $filename = 'tests/data/Reader/HTML/badhtml.html';
  20. $reader = new Html();
  21. self::assertTrue($reader->canRead($filename));
  22. $this->expectException(ReaderException::class);
  23. $reader->load($filename);
  24. }
  25. public function testNonHtml(): void
  26. {
  27. $filename = __FILE__;
  28. $reader = new Html();
  29. self::assertFalse($reader->canRead($filename));
  30. $this->expectException(ReaderException::class);
  31. $reader->load($filename);
  32. }
  33. public function testInvalidFilename(): void
  34. {
  35. $reader = new Html();
  36. self::assertEquals(0, $reader->getSheetIndex());
  37. self::assertFalse($reader->canRead(''));
  38. }
  39. public function providerCanReadVerySmallFile(): array
  40. {
  41. $padding = str_repeat('a', 2048);
  42. return [
  43. [true, ' <html> ' . $padding . ' </html> '],
  44. [true, ' <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html>' . $padding . '</html>'],
  45. [true, '<html></html>'],
  46. [false, ''],
  47. ];
  48. }
  49. /**
  50. * @dataProvider providerCanReadVerySmallFile
  51. *
  52. * @param bool $expected
  53. * @param string $content
  54. */
  55. public function testCanReadVerySmallFile($expected, $content): void
  56. {
  57. $filename = HtmlHelper::createHtml($content);
  58. $reader = new Html();
  59. $actual = $reader->canRead($filename);
  60. self::assertSame($expected, $actual);
  61. unlink($filename);
  62. }
  63. public function testBackgroundColorInRanding(): void
  64. {
  65. $html = '<table>
  66. <tr>
  67. <td style="background-color: #0000FF;color: #FFFFFF">Blue background</td>
  68. <td style="background-color: unknown1;color: unknown2">Unknown fore/background</td>
  69. </tr>
  70. </table>';
  71. $filename = HtmlHelper::createHtml($html);
  72. $spreadsheet = HtmlHelper::loadHtmlIntoSpreadsheet($filename, true);
  73. $firstSheet = $spreadsheet->getSheet(0);
  74. $style = $firstSheet->getCell('A1')->getStyle();
  75. self::assertEquals('FFFFFF', $style->getFont()->getColor()->getRGB());
  76. self::assertEquals('0000FF', $style->getFill()->getStartColor()->getRGB());
  77. self::assertEquals('0000FF', $style->getFill()->getEndColor()->getRGB());
  78. $style = $firstSheet->getCell('B1')->getStyle();
  79. self::assertEquals('000000', $style->getFont()->getColor()->getRGB());
  80. self::assertEquals('000000', $style->getFill()->getEndColor()->getRGB());
  81. self::assertEquals('FFFFFF', $style->getFill()->getstartColor()->getRGB());
  82. }
  83. public function testCanApplyInlineFontStyles(): void
  84. {
  85. $html = '<table>
  86. <tr>
  87. <td style="font-size: 16px;">16px</td>
  88. <td style="font-family: \'Times New Roman\'">Times New Roman</td>
  89. <td style="font-weight: bold;">Bold</td>
  90. <td style="font-style: italic;">Italic</td>
  91. <td style="text-decoration: underline;">Underline</td>
  92. <td style="text-decoration: line-through;">Line through</td>
  93. </tr>
  94. </table>';
  95. $filename = HtmlHelper::createHtml($html);
  96. $spreadsheet = HtmlHelper::loadHtmlIntoSpreadsheet($filename, true);
  97. $firstSheet = $spreadsheet->getSheet(0);
  98. $style = $firstSheet->getCell('A1')->getStyle();
  99. self::assertEquals(16, $style->getFont()->getSize());
  100. $style = $firstSheet->getCell('B1')->getStyle();
  101. self::assertEquals('Times New Roman', $style->getFont()->getName());
  102. $style = $firstSheet->getCell('C1')->getStyle();
  103. self::assertTrue($style->getFont()->getBold());
  104. $style = $firstSheet->getCell('D1')->getStyle();
  105. self::assertTrue($style->getFont()->getItalic());
  106. $style = $firstSheet->getCell('E1')->getStyle();
  107. self::assertEquals(Font::UNDERLINE_SINGLE, $style->getFont()->getUnderline());
  108. $style = $firstSheet->getCell('F1')->getStyle();
  109. self::assertTrue($style->getFont()->getStrikethrough());
  110. }
  111. public function testCanApplyInlineWidth(): void
  112. {
  113. $html = '<table>
  114. <tr>
  115. <td width="50">50px</td>
  116. <td style="width: 100px;">100px</td>
  117. <td width="50px">50px</td>
  118. </tr>
  119. </table>';
  120. $filename = HtmlHelper::createHtml($html);
  121. $spreadsheet = HtmlHelper::loadHtmlIntoSpreadsheet($filename, true);
  122. $firstSheet = $spreadsheet->getSheet(0);
  123. $dimension = $firstSheet->getColumnDimension('A');
  124. self::assertNotNull($dimension);
  125. self::assertEquals(50, $dimension->getWidth());
  126. $dimension = $firstSheet->getColumnDimension('B');
  127. self::assertNotNull($dimension);
  128. self::assertEquals(100, $dimension->getWidth('px'));
  129. $dimension = $firstSheet->getColumnDimension('C');
  130. self::assertNotNull($dimension);
  131. self::assertEquals(50, $dimension->getWidth('px'));
  132. }
  133. public function testCanApplyInlineHeight(): void
  134. {
  135. $html = '<table>
  136. <tr>
  137. <td height="50">1</td>
  138. </tr>
  139. <tr>
  140. <td style="height: 100px;">2</td>
  141. </tr>
  142. <tr>
  143. <td height="50px">1</td>
  144. </tr>
  145. </table>';
  146. $filename = HtmlHelper::createHtml($html);
  147. $spreadsheet = HtmlHelper::loadHtmlIntoSpreadsheet($filename, true);
  148. $firstSheet = $spreadsheet->getSheet(0);
  149. $dimension = $firstSheet->getRowDimension(1);
  150. self::assertNotNull($dimension);
  151. self::assertEquals(50, $dimension->getRowHeight());
  152. $dimension = $firstSheet->getRowDimension(2);
  153. self::assertNotNull($dimension);
  154. self::assertEquals(100, $dimension->getRowHeight('px'));
  155. $dimension = $firstSheet->getRowDimension(3);
  156. self::assertNotNull($dimension);
  157. self::assertEquals(50, $dimension->getRowHeight('px'));
  158. }
  159. public function testCanApplyAlignment(): void
  160. {
  161. $html = '<table>
  162. <tr>
  163. <td align="center">Center align</td>
  164. <td valign="center">Center valign</td>
  165. <td style="text-align: center;">Center align</td>
  166. <td style="vertical-align: center;">Center valign</td>
  167. <td style="text-indent: 10px;">Text indent</td>
  168. <td style="word-wrap: break-word;">Wraptext</td>
  169. </tr>
  170. </table>';
  171. $filename = HtmlHelper::createHtml($html);
  172. $spreadsheet = HtmlHelper::loadHtmlIntoSpreadsheet($filename, true);
  173. $firstSheet = $spreadsheet->getSheet(0);
  174. $style = $firstSheet->getCell('A1')->getStyle();
  175. self::assertEquals(Alignment::HORIZONTAL_CENTER, $style->getAlignment()->getHorizontal());
  176. $style = $firstSheet->getCell('B1')->getStyle();
  177. self::assertEquals(Alignment::VERTICAL_CENTER, $style->getAlignment()->getVertical());
  178. $style = $firstSheet->getCell('C1')->getStyle();
  179. self::assertEquals(Alignment::HORIZONTAL_CENTER, $style->getAlignment()->getHorizontal());
  180. $style = $firstSheet->getCell('D1')->getStyle();
  181. self::assertEquals(Alignment::VERTICAL_CENTER, $style->getAlignment()->getVertical());
  182. $style = $firstSheet->getCell('E1')->getStyle();
  183. self::assertEquals(10, $style->getAlignment()->getIndent());
  184. $style = $firstSheet->getCell('F1')->getStyle();
  185. self::assertTrue($style->getAlignment()->getWrapText());
  186. }
  187. public function testCanApplyInlineDataFormat(): void
  188. {
  189. $html = '<table>
  190. <tr>
  191. <td data-format="mmm-yy">2019-02-02 12:34:00</td>
  192. </tr>
  193. </table>';
  194. $filename = HtmlHelper::createHtml($html);
  195. $spreadsheet = HtmlHelper::loadHtmlIntoSpreadsheet($filename, true);
  196. $firstSheet = $spreadsheet->getSheet(0);
  197. $style = $firstSheet->getCell('A1')->getStyle();
  198. self::assertEquals('mmm-yy', $style->getNumberFormat()->getFormatCode());
  199. }
  200. public function testCanApplyCellWrapping(): void
  201. {
  202. $html = '<table>
  203. <tr>
  204. <td>Hello World</td>
  205. </tr>
  206. <tr>
  207. <td>Hello<br />World</td>
  208. </tr>
  209. <tr>
  210. <td>Hello<br>World</td>
  211. </tr>
  212. </table>';
  213. $filename = HtmlHelper::createHtml($html);
  214. $spreadsheet = HtmlHelper::loadHtmlIntoSpreadsheet($filename, true);
  215. $firstSheet = $spreadsheet->getSheet(0);
  216. $cellStyle = $firstSheet->getStyle('A1');
  217. self::assertFalse($cellStyle->getAlignment()->getWrapText());
  218. $cellStyle = $firstSheet->getStyle('A2');
  219. self::assertTrue($cellStyle->getAlignment()->getWrapText());
  220. $cellValue = $firstSheet->getCell('A2')->getValue();
  221. self::assertStringContainsString("\n", $cellValue);
  222. $cellStyle = $firstSheet->getStyle('A3');
  223. self::assertTrue($cellStyle->getAlignment()->getWrapText());
  224. $cellValue = $firstSheet->getCell('A3')->getValue();
  225. self::assertStringContainsString("\n", $cellValue);
  226. }
  227. public function testRowspanInRendering(): void
  228. {
  229. $filename = 'tests/data/Reader/HTML/rowspan.html';
  230. $reader = new Html();
  231. $spreadsheet = $reader->load($filename);
  232. $actual = $spreadsheet->getActiveSheet()->getMergeCells();
  233. self::assertSame(['A2:C2' => 'A2:C2'], $actual);
  234. }
  235. public function testTextIndentUseRowspan(): void
  236. {
  237. $html = '<table>
  238. <tr>
  239. <td>1</td>
  240. <td rowspan="2" style="vertical-align: center;">Center Align</td>
  241. <td>Row</td>
  242. </tr>
  243. <tr>
  244. <td>2</td>
  245. <td style="text-indent:10px">Text Indent</td>
  246. </tr>
  247. </table>';
  248. $filename = HtmlHelper::createHtml($html);
  249. $spreadsheet = HtmlHelper::loadHtmlIntoSpreadsheet($filename, true);
  250. $firstSheet = $spreadsheet->getSheet(0);
  251. $style = $firstSheet->getCell('C2')->getStyle();
  252. self::assertEquals(10, $style->getAlignment()->getIndent());
  253. }
  254. public function testBorderWithRowspanAndColspan(): void
  255. {
  256. $html = '<table>
  257. <tr>
  258. <td style="border: 1px solid black;">NOT SPANNED</td>
  259. <td rowspan="2" colspan="2" style="border: 1px solid black;">SPANNED</td>
  260. </tr>
  261. <tr>
  262. <td style="border: 1px solid black;">NOT SPANNED</td>
  263. </tr>
  264. </table>';
  265. $reader = new Html();
  266. $spreadsheet = $reader->loadFromString($html);
  267. $firstSheet = $spreadsheet->getSheet(0);
  268. $style = $firstSheet->getStyle('B1:C2');
  269. $borders = $style->getBorders();
  270. $totalBorders = [
  271. $borders->getTop(),
  272. $borders->getLeft(),
  273. $borders->getBottom(),
  274. $borders->getRight(),
  275. ];
  276. foreach ($totalBorders as $border) {
  277. self::assertEquals(Border::BORDER_THIN, $border->getBorderStyle());
  278. }
  279. }
  280. public function testBorderWithColspan(): void
  281. {
  282. $html = '<table>
  283. <tr>
  284. <td style="border: 1px solid black;">NOT SPANNED</td>
  285. <td colspan="2" style="border: 1px solid black;">SPANNED</td>
  286. </tr>
  287. <tr>
  288. <td style="border: 1px solid black;">NOT SPANNED</td>
  289. </tr>
  290. </table>';
  291. $reader = new Html();
  292. $spreadsheet = $reader->loadFromString($html);
  293. $firstSheet = $spreadsheet->getSheet(0);
  294. $style = $firstSheet->getStyle('B1:B2');
  295. $borders = $style->getBorders();
  296. $totalBorders = [
  297. $borders->getTop(),
  298. $borders->getLeft(),
  299. $borders->getBottom(),
  300. $borders->getRight(),
  301. ];
  302. foreach ($totalBorders as $border) {
  303. self::assertEquals(Border::BORDER_THIN, $border->getBorderStyle());
  304. }
  305. }
  306. }