+<?php
+
+namespace Tests\Exports;
+
+use Illuminate\Http\UploadedFile;
+use Illuminate\Testing\TestResponse;
+use Tests\TestCase;
+use ZipArchive;
+
+class ZipImportTest extends TestCase
+{
+ public function test_import_page_view()
+ {
+ $resp = $this->asAdmin()->get('/import');
+ $resp->assertSee('Import');
+ $this->withHtml($resp)->assertElementExists('form input[type="file"][name="file"]');
+ }
+
+ public function test_permissions_needed_for_import_page()
+ {
+ $user = $this->users->viewer();
+ $this->actingAs($user);
+
+ $resp = $this->get('/books');
+ $this->withHtml($resp)->assertLinkNotExists(url('/import'));
+ $resp = $this->get('/import');
+ $resp->assertRedirect('/');
+
+ $this->permissions->grantUserRolePermissions($user, ['content-import']);
+
+ $resp = $this->get('/books');
+ $this->withHtml($resp)->assertLinkExists(url('/import'));
+ $resp = $this->get('/import');
+ $resp->assertOk();
+ $resp->assertSeeText('Select ZIP file to upload');
+ }
+
+ public function test_zip_read_errors_are_shown_on_validation()
+ {
+ $invalidUpload = $this->files->uploadedImage('image.zip');
+
+ $this->asAdmin();
+ $resp = $this->runImportFromFile($invalidUpload);
+ $resp->assertRedirect('/import');
+
+ $resp = $this->followRedirects($resp);
+ $resp->assertSeeText('Could not read ZIP file');
+ }
+
+ public function test_error_shown_if_missing_data()
+ {
+ $zipFile = tempnam(sys_get_temp_dir(), 'bstest-');
+ $zip = new ZipArchive();
+ $zip->open($zipFile, ZipArchive::CREATE);
+ $zip->addFromString('beans', 'cat');
+ $zip->close();
+
+ $this->asAdmin();
+ $upload = new UploadedFile($zipFile, 'upload.zip', 'application/zip', null, true);
+ $resp = $this->runImportFromFile($upload);
+ $resp->assertRedirect('/import');
+
+ $resp = $this->followRedirects($resp);
+ $resp->assertSeeText('Could not find and decode ZIP data.json content.');
+ }
+
+ public function test_error_shown_if_no_importable_key()
+ {
+ $this->asAdmin();
+ $resp = $this->runImportFromFile($this->zipUploadFromData([
+ 'instance' => []
+ ]));
+
+ $resp->assertRedirect('/import');
+ $resp = $this->followRedirects($resp);
+ $resp->assertSeeText('ZIP file data has no expected book, chapter or page content.');
+ }
+
+ public function test_zip_data_validation_messages_shown()
+ {
+ $this->asAdmin();
+ $resp = $this->runImportFromFile($this->zipUploadFromData([
+ 'book' => [
+ 'id' => 4,
+ 'pages' => [
+ 'cat',
+ [
+ 'name' => 'My inner page',
+ 'tags' => [
+ [
+ 'value' => 5
+ ]
+ ],
+ ]
+ ],
+ ]
+ ]));
+
+ $resp->assertRedirect('/import');
+ $resp = $this->followRedirects($resp);
+
+ $resp->assertSeeText('[book.name]: The name field is required.');
+ $resp->assertSeeText('[book.pages.0.0]: Data object expected but "string" found.');
+ $resp->assertSeeText('[book.pages.1.tags.0.name]: The name field is required.');
+ $resp->assertSeeText('[book.pages.1.tags.0.value]: The value must be a string.');
+ }
+
+ protected function runImportFromFile(UploadedFile $file): TestResponse
+ {
+ return $this->call('POST', '/import', [], [], ['file' => $file]);
+ }
+
+ protected function zipUploadFromData(array $data): UploadedFile
+ {
+ $zipFile = tempnam(sys_get_temp_dir(), 'bstest-');
+
+ $zip = new ZipArchive();
+ $zip->open($zipFile, ZipArchive::CREATE);
+ $zip->addFromString('data.json', json_encode($data));
+ $zip->close();
+
+ return new UploadedFile($zipFile, 'upload.zip', 'application/zip', null, true);
+ }
+}