ExcelTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. <?php
  2. namespace Maatwebsite\Excel\Tests;
  3. use Illuminate\Contracts\View\View;
  4. use Illuminate\Http\UploadedFile;
  5. use Illuminate\Support\Collection;
  6. use Maatwebsite\Excel\Concerns\Exportable;
  7. use Maatwebsite\Excel\Concerns\FromCollection;
  8. use Maatwebsite\Excel\Concerns\FromView;
  9. use Maatwebsite\Excel\Concerns\Importable;
  10. use Maatwebsite\Excel\Concerns\RegistersEventListeners;
  11. use Maatwebsite\Excel\Concerns\ToArray;
  12. use Maatwebsite\Excel\Concerns\WithCustomCsvSettings;
  13. use Maatwebsite\Excel\Concerns\WithEvents;
  14. use Maatwebsite\Excel\Excel;
  15. use Maatwebsite\Excel\Facades\Excel as ExcelFacade;
  16. use Maatwebsite\Excel\Importer;
  17. use Maatwebsite\Excel\Tests\Data\Stubs\EmptyExport;
  18. use Maatwebsite\Excel\Tests\Helpers\FileHelper;
  19. use PHPUnit\Framework\Assert;
  20. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  21. class ExcelTest extends TestCase
  22. {
  23. /**
  24. * @var Excel
  25. */
  26. protected $SUT;
  27. protected function setUp(): void
  28. {
  29. parent::setUp();
  30. $this->SUT = $this->app->make(Excel::class);
  31. }
  32. /**
  33. * @test
  34. */
  35. public function can_download_an_export_object_with_facade()
  36. {
  37. $export = new EmptyExport();
  38. $response = ExcelFacade::download($export, 'filename.xlsx');
  39. $this->assertInstanceOf(BinaryFileResponse::class, $response);
  40. $this->assertEquals('attachment; filename=filename.xlsx', str_replace('"', '', $response->headers->get('Content-Disposition')));
  41. }
  42. /**
  43. * @test
  44. */
  45. public function can_download_an_export_object()
  46. {
  47. $export = new EmptyExport();
  48. $response = $this->SUT->download($export, 'filename.xlsx');
  49. $this->assertInstanceOf(BinaryFileResponse::class, $response);
  50. $this->assertEquals('attachment; filename=filename.xlsx', str_replace('"', '', $response->headers->get('Content-Disposition')));
  51. }
  52. /**
  53. * @test
  54. */
  55. public function can_store_an_export_object_on_default_disk()
  56. {
  57. $export = new EmptyExport;
  58. $name = 'filename.xlsx';
  59. $path = FileHelper::absolutePath($name, 'local');
  60. @unlink($path);
  61. $this->assertFileMissing($path);
  62. $response = $this->SUT->store($export, $name);
  63. $this->assertTrue($response);
  64. $this->assertFileExists($path);
  65. }
  66. /**
  67. * @test
  68. */
  69. public function can_store_an_export_object_on_another_disk()
  70. {
  71. $export = new EmptyExport;
  72. $name = 'filename.xlsx';
  73. $path = FileHelper::absolutePath($name, 'test');
  74. @unlink($path);
  75. $this->assertFileMissing($path);
  76. $response = $this->SUT->store($export, $name, 'test');
  77. $this->assertTrue($response);
  78. $this->assertFileExists($path);
  79. }
  80. /**
  81. * @test
  82. */
  83. public function can_store_csv_export_with_default_settings()
  84. {
  85. $export = new EmptyExport;
  86. $name = 'filename.csv';
  87. $path = FileHelper::absolutePath($name, 'local');
  88. @unlink($path);
  89. $this->assertFileMissing($path);
  90. $response = $this->SUT->store($export, $name);
  91. $this->assertTrue($response);
  92. $this->assertFileExists($path);
  93. }
  94. /**
  95. * @test
  96. */
  97. public function can_get_raw_export_contents()
  98. {
  99. $export = new EmptyExport;
  100. $response = $this->SUT->raw($export, Excel::XLSX);
  101. $this->assertNotEmpty($response);
  102. }
  103. /**
  104. * @test
  105. */
  106. public function can_store_tsv_export_with_default_settings()
  107. {
  108. $export = new EmptyExport;
  109. $name = 'filename.tsv';
  110. $path = FileHelper::absolutePath($name, 'local');
  111. @unlink($path);
  112. $this->assertFileMissing($path);
  113. $response = $this->SUT->store($export, $name);
  114. $this->assertTrue($response);
  115. $this->assertFileExists($path);
  116. }
  117. /**
  118. * @test
  119. */
  120. public function can_store_csv_export_with_custom_settings()
  121. {
  122. $export = new class implements WithEvents, FromCollection, WithCustomCsvSettings
  123. {
  124. use RegistersEventListeners;
  125. /**
  126. * @return Collection
  127. */
  128. public function collection()
  129. {
  130. return collect([
  131. ['A1', 'B1'],
  132. ['A2', 'B2'],
  133. ]);
  134. }
  135. /**
  136. * @return array
  137. */
  138. public function getCsvSettings(): array
  139. {
  140. return [
  141. 'line_ending' => PHP_EOL,
  142. 'enclosure' => '"',
  143. 'delimiter' => ';',
  144. 'include_separator_line' => true,
  145. 'excel_compatibility' => false,
  146. ];
  147. }
  148. };
  149. $this->SUT->store($export, 'filename.csv');
  150. $contents = file_get_contents(__DIR__ . '/Data/Disks/Local/filename.csv');
  151. $this->assertStringContains('sep=;', $contents);
  152. $this->assertStringContains('"A1";"B1"', $contents);
  153. $this->assertStringContains('"A2";"B2"', $contents);
  154. }
  155. /**
  156. * @test
  157. */
  158. public function cannot_use_from_collection_and_from_view_on_same_export()
  159. {
  160. $this->expectException(\Maatwebsite\Excel\Exceptions\ConcernConflictException::class);
  161. $this->expectExceptionMessage('Cannot use FromQuery, FromArray or FromCollection and FromView on the same sheet');
  162. $export = new class implements FromCollection, FromView
  163. {
  164. use Exportable;
  165. /**
  166. * @return Collection
  167. */
  168. public function collection()
  169. {
  170. return collect();
  171. }
  172. /**
  173. * @return View
  174. */
  175. public function view(): View
  176. {
  177. return view('users');
  178. }
  179. };
  180. $export->download('filename.csv');
  181. }
  182. /**
  183. * @test
  184. */
  185. public function can_import_a_simple_xlsx_file_to_array()
  186. {
  187. $import = new class
  188. {
  189. use Importable;
  190. };
  191. $this->assertEquals([
  192. [
  193. ['test', 'test'],
  194. ['test', 'test'],
  195. ],
  196. ], $import->toArray('import.xlsx'));
  197. }
  198. /**
  199. * @test
  200. */
  201. public function can_import_a_simple_xlsx_file_to_collection()
  202. {
  203. $import = new class
  204. {
  205. use Importable;
  206. };
  207. $this->assertEquals(new Collection([
  208. new Collection([
  209. new Collection(['test', 'test']),
  210. new Collection(['test', 'test']),
  211. ]),
  212. ]), $import->toCollection('import.xlsx'));
  213. }
  214. /**
  215. * @test
  216. */
  217. public function can_import_a_simple_xlsx_file_to_collection_without_import_object()
  218. {
  219. $this->assertEquals(new Collection([
  220. new Collection([
  221. new Collection(['test', 'test']),
  222. new Collection(['test', 'test']),
  223. ]),
  224. ]), ExcelFacade::toCollection(null, 'import.xlsx'));
  225. }
  226. /**
  227. * @test
  228. */
  229. public function can_import_a_simple_xlsx_file()
  230. {
  231. $import = new class implements ToArray
  232. {
  233. /**
  234. * @param array $array
  235. */
  236. public function array(array $array)
  237. {
  238. Assert::assertEquals([
  239. ['test', 'test'],
  240. ['test', 'test'],
  241. ], $array);
  242. }
  243. };
  244. $imported = $this->SUT->import($import, 'import.xlsx');
  245. $this->assertInstanceOf(Importer::class, $imported);
  246. }
  247. /**
  248. * @test
  249. */
  250. public function can_import_a_tsv_file()
  251. {
  252. $import = new class implements ToArray, WithCustomCsvSettings
  253. {
  254. /**
  255. * @param array $array
  256. */
  257. public function array(array $array)
  258. {
  259. Assert::assertEquals([
  260. 'tconst',
  261. 'titleType',
  262. 'primaryTitle',
  263. 'originalTitle',
  264. 'isAdult',
  265. 'startYear',
  266. 'endYear',
  267. 'runtimeMinutes',
  268. 'genres',
  269. ], $array[0]);
  270. }
  271. /**
  272. * @return array
  273. */
  274. public function getCsvSettings(): array
  275. {
  276. return [
  277. 'delimiter' => "\t",
  278. ];
  279. }
  280. };
  281. $imported = $this->SUT->import($import, 'import-titles.tsv');
  282. $this->assertInstanceOf(Importer::class, $imported);
  283. }
  284. /**
  285. * @test
  286. */
  287. public function can_chain_imports()
  288. {
  289. $import1 = new class implements ToArray
  290. {
  291. /**
  292. * @param array $array
  293. */
  294. public function array(array $array)
  295. {
  296. Assert::assertEquals([
  297. ['test', 'test'],
  298. ['test', 'test'],
  299. ], $array);
  300. }
  301. };
  302. $import2 = new class implements ToArray
  303. {
  304. /**
  305. * @param array $array
  306. */
  307. public function array(array $array)
  308. {
  309. Assert::assertEquals([
  310. ['test', 'test'],
  311. ['test', 'test'],
  312. ], $array);
  313. }
  314. };
  315. $imported = $this->SUT
  316. ->import($import1, 'import.xlsx')
  317. ->import($import2, 'import.xlsx');
  318. $this->assertInstanceOf(Importer::class, $imported);
  319. }
  320. /**
  321. * @test
  322. */
  323. public function can_import_a_simple_xlsx_file_from_uploaded_file()
  324. {
  325. $import = new class implements ToArray
  326. {
  327. /**
  328. * @param array $array
  329. */
  330. public function array(array $array)
  331. {
  332. Assert::assertEquals([
  333. ['test', 'test'],
  334. ['test', 'test'],
  335. ], $array);
  336. }
  337. };
  338. $this->SUT->import($import, $this->givenUploadedFile(__DIR__ . '/Data/Disks/Local/import.xlsx'));
  339. }
  340. /**
  341. * @test
  342. */
  343. public function can_import_a_simple_xlsx_file_from_real_path()
  344. {
  345. $import = new class implements ToArray
  346. {
  347. /**
  348. * @param array $array
  349. */
  350. public function array(array $array)
  351. {
  352. Assert::assertEquals([
  353. ['test', 'test'],
  354. ['test', 'test'],
  355. ], $array);
  356. }
  357. };
  358. $this->SUT->import($import, __DIR__ . '/Data/Disks/Local/import.xlsx');
  359. }
  360. /**
  361. * @test
  362. */
  363. public function import_will_throw_error_when_no_reader_type_could_be_detected_when_no_extension()
  364. {
  365. $this->expectException(\Maatwebsite\Excel\Exceptions\NoTypeDetectedException::class);
  366. $import = new class implements ToArray
  367. {
  368. /**
  369. * @param array $array
  370. */
  371. public function array(array $array)
  372. {
  373. Assert::assertEquals([
  374. ['test', 'test'],
  375. ['test', 'test'],
  376. ], $array);
  377. }
  378. };
  379. $this->SUT->import($import, UploadedFile::fake()->create('import'));
  380. }
  381. /**
  382. * @test
  383. */
  384. public function import_will_throw_error_when_no_reader_type_could_be_detected_with_unknown_extension()
  385. {
  386. $this->expectException(\Maatwebsite\Excel\Exceptions\NoTypeDetectedException::class);
  387. $import = new class implements ToArray
  388. {
  389. /**
  390. * @param array $array
  391. */
  392. public function array(array $array)
  393. {
  394. //
  395. }
  396. };
  397. $this->SUT->import($import, 'unknown-reader-type.zip');
  398. }
  399. /**
  400. * @test
  401. */
  402. public function can_import_without_extension_with_explicit_reader_type()
  403. {
  404. $import = new class implements ToArray
  405. {
  406. /**
  407. * @param array $array
  408. */
  409. public function array(array $array)
  410. {
  411. Assert::assertEquals([
  412. ['test', 'test'],
  413. ['test', 'test'],
  414. ], $array);
  415. }
  416. };
  417. $this->SUT->import(
  418. $import,
  419. $this->givenUploadedFile(__DIR__ . '/Data/Disks/Local/import.xlsx', 'import'),
  420. null,
  421. Excel::XLSX
  422. );
  423. }
  424. }