3 namespace Tests\Exports;
5 use BookStack\Entities\Models\Book;
6 use BookStack\Entities\Models\Chapter;
7 use BookStack\Entities\Models\Page;
8 use BookStack\Exports\ZipExports\ZipImportRunner;
9 use BookStack\Uploads\Image;
12 class ZipImportRunnerTest extends TestCase
14 protected ZipImportRunner $runner;
16 protected function setUp(): void
19 $this->runner = app()->make(ZipImportRunner::class);
22 public function test_book_import()
24 $testImagePath = $this->files->testFilePath('test-image.png');
25 $testFilePath = $this->files->testFilePath('test-file.txt');
26 $import = ZipTestHelper::importFromData([], [
29 'name' => 'Import test',
30 'cover' => 'book_cover_image',
31 'description_html' => '<p><a href="[[bsexport:page:3]]">Link to chapter page</a></p>',
33 ['name' => 'Animal', 'value' => 'Cat'],
34 ['name' => 'Category', 'value' => 'Test'],
39 'name' => 'Chapter A',
40 'description_html' => '<p><a href="[[bsexport:book:5]]">Link to book</a></p>',
43 ['name' => 'Reviewed'],
44 ['name' => 'Category', 'value' => 'Test Chapter'],
52 <p><a href="[[bsexport:page:3]]">Link to self</a></p>
53 <p><a href="[[bsexport:image:1]]">Link to cat image</a></p>
54 <p><a href="[[bsexport:attachment:4]]">Link to text attachment</a></p>',
56 ['name' => 'Unreviewed'],
61 'name' => 'Text attachment',
62 'file' => 'file_attachment'
66 'link' => 'https://example.com/cats',
78 'name' => 'Dog Drawing',
87 'name' => 'Chapter child B',
94 'markdown' => '[Link to text]([[bsexport:attachment:4]]?scale=big)',
100 'book_cover_image' => $testImagePath,
101 'file_attachment' => $testFilePath,
102 'cat_image' => $testImagePath,
103 'dog_image' => $testImagePath,
107 /** @var Book $book */
108 $book = $this->runner->run($import);
111 $this->assertEquals('Import test', $book->name);
112 $this->assertFileExists(public_path($book->cover->path));
113 $this->assertCount(2, $book->tags);
114 $this->assertEquals('Cat', $book->tags()->first()->value);
115 $this->assertCount(2, $book->chapters);
116 $this->assertEquals(1, $book->directPages()->count());
119 $chapterA = $book->chapters()->where('name', 'Chapter A')->first();
120 $this->assertCount(2, $chapterA->tags);
121 $firstChapterTag = $chapterA->tags()->first();
122 $this->assertEquals('Reviewed', $firstChapterTag->name);
123 $this->assertEquals('', $firstChapterTag->value);
124 $this->assertCount(1, $chapterA->pages);
127 /** @var Page $pageA */
128 $pageA = $chapterA->pages->first();
129 $this->assertEquals('Page A', $pageA->name);
130 $this->assertCount(1, $pageA->tags);
131 $firstPageTag = $pageA->tags()->first();
132 $this->assertEquals('Unreviewed', $firstPageTag->name);
133 $this->assertCount(2, $pageA->attachments);
134 $firstAttachment = $pageA->attachments->first();
135 $this->assertEquals('Text attachment', $firstAttachment->name);
136 $this->assertFileEquals($testFilePath, storage_path($firstAttachment->path));
137 $this->assertFalse($firstAttachment->external);
138 $secondAttachment = $pageA->attachments->last();
139 $this->assertEquals('Cats', $secondAttachment->name);
140 $this->assertEquals('https://example.com/cats', $secondAttachment->path);
141 $this->assertTrue($secondAttachment->external);
142 $pageAImages = Image::where('uploaded_to', '=', $pageA->id)->whereIn('type', ['gallery', 'drawio'])->get();
143 $this->assertCount(2, $pageAImages);
144 $this->assertEquals('Cat', $pageAImages[0]->name);
145 $this->assertEquals('gallery', $pageAImages[0]->type);
146 $this->assertFileEquals($testImagePath, public_path($pageAImages[0]->path));
147 $this->assertEquals('Dog Drawing', $pageAImages[1]->name);
148 $this->assertEquals('drawio', $pageAImages[1]->type);
151 $children = $book->getDirectVisibleChildren()->values()->all();
152 $this->assertEquals($children[0]->name, 'Chapter A');
153 $this->assertEquals($children[1]->name, 'Page C');
154 $this->assertEquals($children[2]->name, 'Chapter child B');
157 $textAttachmentUrl = $firstAttachment->getUrl();
158 $this->assertStringContainsString($pageA->getUrl(), $book->description_html);
159 $this->assertStringContainsString($book->getUrl(), $chapterA->description_html);
160 $this->assertStringContainsString($pageA->getUrl(), $pageA->html);
161 $this->assertStringContainsString($pageAImages[0]->getThumb(1680, null, true), $pageA->html);
162 $this->assertStringContainsString($firstAttachment->getUrl(), $pageA->html);
164 // Reference in converted markdown
165 $pageC = $children[1];
166 $this->assertStringContainsString("href=\"{$textAttachmentUrl}?scale=big\"", $pageC->html);
168 ZipTestHelper::deleteZipForImport($import);
171 public function test_chapter_import()
173 $testImagePath = $this->files->testFilePath('test-image.png');
174 $testFilePath = $this->files->testFilePath('test-file.txt');
175 $parent = $this->entities->book();
177 $import = ZipTestHelper::importFromData([], [
180 'name' => 'Chapter A',
181 'description_html' => '<p><a href="[[bsexport:page:3]]">Link to page</a></p>',
184 ['name' => 'Reviewed', 'value' => '2024'],
191 'html' => '<p><a href="[[bsexport:chapter:6]]">Link to chapter</a></p>
192 <p><a href="[[bsexport:image:2]]">Link to dog drawing</a></p>
193 <p><a href="[[bsexport:attachment:4]]">Link to text attachment</a></p>',
195 ['name' => 'Unreviewed'],
200 'name' => 'Text attachment',
201 'file' => 'file_attachment'
207 'name' => 'Dog Drawing',
209 'file' => 'dog_image'
215 'markdown' => '[Link to page A]([[bsexport:page:3]])',
221 'file_attachment' => $testFilePath,
222 'dog_image' => $testImagePath,
226 /** @var Chapter $chapter */
227 $chapter = $this->runner->run($import, $parent);
230 $this->assertEquals('Chapter A', $chapter->name);
231 $this->assertEquals($parent->id, $chapter->book_id);
232 $this->assertCount(1, $chapter->tags);
233 $firstChapterTag = $chapter->tags()->first();
234 $this->assertEquals('Reviewed', $firstChapterTag->name);
235 $this->assertEquals('2024', $firstChapterTag->value);
236 $this->assertCount(2, $chapter->pages);
239 /** @var Page $pageA */
240 $pageA = $chapter->pages->first();
241 $this->assertEquals('Page A', $pageA->name);
242 $this->assertCount(1, $pageA->tags);
243 $this->assertCount(1, $pageA->attachments);
244 $pageAImages = Image::where('uploaded_to', '=', $pageA->id)->whereIn('type', ['gallery', 'drawio'])->get();
245 $this->assertCount(1, $pageAImages);
248 $attachment = $pageA->attachments->first();
249 $this->assertStringContainsString($pageA->getUrl(), $chapter->description_html);
250 $this->assertStringContainsString($chapter->getUrl(), $pageA->html);
251 $this->assertStringContainsString($pageAImages[0]->url, $pageA->html);
252 $this->assertStringContainsString($attachment->getUrl(), $pageA->html);
254 ZipTestHelper::deleteZipForImport($import);
257 public function test_page_import()
259 $testImagePath = $this->files->testFilePath('test-image.png');
260 $testFilePath = $this->files->testFilePath('test-file.txt');
261 $parent = $this->entities->chapter();
263 $import = ZipTestHelper::importFromData([], [
268 'html' => '<p><a href="[[bsexport:page:3]]">Link to self</a></p>
269 <p><a href="[[bsexport:image:2]]">Link to dog drawing</a></p>
270 <p><a href="[[bsexport:attachment:4]]">Link to text attachment</a></p>',
272 ['name' => 'Unreviewed'],
277 'name' => 'Text attachment',
278 'file' => 'file_attachment'
284 'name' => 'Dog Drawing',
286 'file' => 'dog_image'
291 'file_attachment' => $testFilePath,
292 'dog_image' => $testImagePath,
296 /** @var Page $page */
297 $page = $this->runner->run($import, $parent);
300 $this->assertEquals('Page A', $page->name);
301 $this->assertCount(1, $page->tags);
302 $this->assertCount(1, $page->attachments);
303 $pageImages = Image::where('uploaded_to', '=', $page->id)->whereIn('type', ['gallery', 'drawio'])->get();
304 $this->assertCount(1, $pageImages);
305 $this->assertFileEquals($testImagePath, public_path($pageImages[0]->path));
308 $this->assertStringContainsString($page->getUrl(), $page->html);
309 $this->assertStringContainsString($pageImages[0]->url, $page->html);
310 $this->assertStringContainsString($page->attachments->first()->getUrl(), $page->html);
312 ZipTestHelper::deleteZipForImport($import);
315 public function test_revert_cleans_up_uploaded_files()
317 $testImagePath = $this->files->testFilePath('test-image.png');
318 $testFilePath = $this->files->testFilePath('test-file.txt');
319 $parent = $this->entities->chapter();
321 $import = ZipTestHelper::importFromData([], [
324 'html' => '<p>Hello</p>',
327 'name' => 'Text attachment',
328 'file' => 'file_attachment'
333 'name' => 'Dog Image',
335 'file' => 'dog_image'
340 'file_attachment' => $testFilePath,
341 'dog_image' => $testImagePath,
345 /** @var Page $page */
346 $page = $this->runner->run($import, $parent);
348 $attachment = $page->attachments->first();
349 $image = Image::query()->where('uploaded_to', '=', $page->id)->where('type', '=', 'gallery')->first();
351 $this->assertFileExists(public_path($image->path));
352 $this->assertFileExists(storage_path($attachment->path));
354 $this->runner->revertStoredFiles();
356 $this->assertFileDoesNotExist(public_path($image->path));
357 $this->assertFileDoesNotExist(storage_path($attachment->path));
359 ZipTestHelper::deleteZipForImport($import);