1 <?php namespace Tests\Entity;
3 use BookStack\Entities\Models\Chapter;
4 use BookStack\Entities\Models\Page;
5 use Illuminate\Support\Facades\Storage;
6 use Illuminate\Support\Str;
9 class ExportTest extends TestCase
12 public function test_page_text_export()
14 $page = Page::first();
17 $resp = $this->get($page->getUrl('/export/plaintext'));
18 $resp->assertStatus(200);
19 $resp->assertSee($page->name);
20 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.txt"');
23 public function test_page_pdf_export()
25 $page = Page::first();
28 $resp = $this->get($page->getUrl('/export/pdf'));
29 $resp->assertStatus(200);
30 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.pdf"');
33 public function test_page_html_export()
35 $page = Page::first();
38 $resp = $this->get($page->getUrl('/export/html'));
39 $resp->assertStatus(200);
40 $resp->assertSee($page->name);
41 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.html"');
44 public function test_book_text_export()
46 $page = Page::first();
50 $resp = $this->get($book->getUrl('/export/plaintext'));
51 $resp->assertStatus(200);
52 $resp->assertSee($book->name);
53 $resp->assertSee($page->name);
54 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.txt"');
57 public function test_book_pdf_export()
59 $page = Page::first();
63 $resp = $this->get($book->getUrl('/export/pdf'));
64 $resp->assertStatus(200);
65 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.pdf"');
68 public function test_book_html_export()
70 $page = Page::first();
74 $resp = $this->get($book->getUrl('/export/html'));
75 $resp->assertStatus(200);
76 $resp->assertSee($book->name);
77 $resp->assertSee($page->name);
78 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $book->slug . '.html"');
81 public function test_book_html_export_shows_chapter_descriptions()
83 $chapterDesc = 'My custom test chapter description ' . Str::random(12);
84 $chapter = Chapter::query()->first();
85 $chapter->description = $chapterDesc;
88 $book = $chapter->book;
91 $resp = $this->get($book->getUrl('/export/html'));
92 $resp->assertSee($chapterDesc);
95 public function test_chapter_text_export()
97 $chapter = Chapter::first();
98 $page = $chapter->pages[0];
101 $resp = $this->get($chapter->getUrl('/export/plaintext'));
102 $resp->assertStatus(200);
103 $resp->assertSee($chapter->name);
104 $resp->assertSee($page->name);
105 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.txt"');
108 public function test_chapter_pdf_export()
110 $chapter = Chapter::first();
113 $resp = $this->get($chapter->getUrl('/export/pdf'));
114 $resp->assertStatus(200);
115 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.pdf"');
118 public function test_chapter_html_export()
120 $chapter = Chapter::first();
121 $page = $chapter->pages[0];
124 $resp = $this->get($chapter->getUrl('/export/html'));
125 $resp->assertStatus(200);
126 $resp->assertSee($chapter->name);
127 $resp->assertSee($page->name);
128 $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $chapter->slug . '.html"');
131 public function test_page_html_export_contains_custom_head_if_set()
133 $page = Page::first();
135 $customHeadContent = "<style>p{color: red;}</style>";
136 $this->setSettings(['app-custom-head' => $customHeadContent]);
138 $resp = $this->asEditor()->get($page->getUrl('/export/html'));
139 $resp->assertSee($customHeadContent);
142 public function test_page_html_export_use_absolute_dates()
144 $page = Page::first();
146 $resp = $this->asEditor()->get($page->getUrl('/export/html'));
147 $resp->assertSee($page->created_at->toDayDateTimeString());
148 $resp->assertDontSee($page->created_at->diffForHumans());
149 $resp->assertSee($page->updated_at->toDayDateTimeString());
150 $resp->assertDontSee($page->updated_at->diffForHumans());
153 public function test_page_export_does_not_include_user_or_revision_links()
155 $page = Page::first();
157 $resp = $this->asEditor()->get($page->getUrl('/export/html'));
158 $resp->assertDontSee($page->getUrl('/revisions'));
159 $resp->assertDontSee($page->createdBy->getProfileUrl());
160 $resp->assertSee($page->createdBy->name);
163 public function test_page_export_sets_right_data_type_for_svg_embeds()
165 $page = Page::first();
166 Storage::disk('local')->makeDirectory('uploads/images/gallery');
167 Storage::disk('local')->put('uploads/images/gallery/svg_test.svg', '<svg></svg>');
168 $page->html = '<img src="http://localhost/uploads/images/gallery/svg_test.svg">';
172 $resp = $this->get($page->getUrl('/export/html'));
173 Storage::disk('local')->delete('uploads/images/gallery/svg_test.svg');
175 $resp->assertStatus(200);
176 $resp->assertSee('<img src="data:image/svg+xml;base64');
179 public function test_page_image_containment_works_on_multiple_images_within_a_single_line()
181 $page = Page::first();
182 Storage::disk('local')->makeDirectory('uploads/images/gallery');
183 Storage::disk('local')->put('uploads/images/gallery/svg_test.svg', '<svg></svg>');
184 Storage::disk('local')->put('uploads/images/gallery/svg_test2.svg', '<svg></svg>');
185 $page->html = '<img src="http://localhost/uploads/images/gallery/svg_test.svg" class="a"><img src="http://localhost/uploads/images/gallery/svg_test2.svg" class="b">';
188 $resp = $this->asEditor()->get($page->getUrl('/export/html'));
189 Storage::disk('local')->delete('uploads/images/gallery/svg_test.svg');
190 Storage::disk('local')->delete('uploads/images/gallery/svg_test2.svg');
192 $resp->assertDontSee('http://localhost/uploads/images/gallery/svg_test');
195 public function test_page_export_contained_html_image_fetches_only_run_when_url_points_to_image_upload_folder()
197 $page = Page::first();
198 $page->html = '<img src="http://localhost/uploads/images/gallery/svg_test.svg"/>'
199 .'<img src="http://localhost/uploads/svg_test.svg"/>'
200 .'<img src="/uploads/svg_test.svg"/>';
201 $storageDisk = Storage::disk('local');
202 $storageDisk->makeDirectory('uploads/images/gallery');
203 $storageDisk->put('uploads/images/gallery/svg_test.svg', '<svg>good</svg>');
204 $storageDisk->put('uploads/svg_test.svg', '<svg>bad</svg>');
207 $resp = $this->asEditor()->get($page->getUrl('/export/html'));
209 $storageDisk->delete('uploads/images/gallery/svg_test.svg');
210 $storageDisk->delete('uploads/svg_test.svg');
212 $resp->assertDontSee('http://localhost/uploads/images/gallery/svg_test.svg');
213 $resp->assertSee('http://localhost/uploads/svg_test.svg');
214 $resp->assertSee('src="/uploads/svg_test.svg"');