]> BookStack Code Mirror - system-cli/blob - tests/Commands/RestoreCommandTest.php
Fixed update-url command not ran, Fixed wrong env contents
[system-cli] / tests / Commands / RestoreCommandTest.php
1 <?php declare(strict_types=1);
2
3 namespace Tests\Commands;
4
5 use mysqli;
6 use Tests\TestCase;
7
8 class RestoreCommandTest extends TestCase
9 {
10
11     public function test_restore_into_cwd_by_default_with_all_content_types()
12     {
13         $mysql = new mysqli('db', 'bookstack', 'bookstack', 'bookstack');
14         $mysql->query('CREATE TABLE xx_testing (labels varchar(255));');
15
16         $result = $mysql->query('SHOW TABLES LIKE \'zz_testing\';');
17         $this->assertEquals(0, mysqli_num_rows($result));
18
19         $zipFile = $this->buildZip(function (\ZipArchive $zip) {
20             $zip->addFromString('.env', "APP_KEY=abc123\nAPP_URL=https://example.com");
21             $zip->addFromString('public/uploads/test.txt', 'hello-public-uploads');
22             $zip->addFromString('storage/uploads/test.txt', 'hello-storage-uploads');
23             $zip->addFromString('themes/test.txt', 'hello-themes');
24             $zip->addFromString('db.sql', "CREATE TABLE zz_testing (names varchar(255));\nINSERT INTO zz_testing values ('barry');");
25         });
26
27         exec('cp -r /var/www/bookstack /var/www/bookstack-restore');
28         chdir('/var/www/bookstack-restore');
29
30         $result = $this->runCommand('restore', [
31             'backup-zip' => $zipFile,
32         ], ['yes', '1']);
33
34         $result->assertSuccessfulExit();
35         $result->assertStdoutContains('✔ .env Config File');
36         $result->assertStdoutContains('✔ Themes Folder');
37         $result->assertStdoutContains('✔ Public File Uploads');
38         $result->assertStdoutContains('✔ Private File Uploads');
39         $result->assertStdoutContains('✔ Database Dump');
40         $result->assertStdoutContains('Restore operation complete!');
41
42         $result = $mysql->query('SELECT * FROM zz_testing where names = \'barry\';');
43         $this->assertEquals(1, mysqli_num_rows($result));
44         $result = $mysql->query('SHOW TABLES LIKE \'xx_testing\';');
45         $this->assertEquals(0, mysqli_num_rows($result));
46
47         $this->assertStringEqualsFile('/var/www/bookstack-restore/public/uploads/test.txt', 'hello-public-uploads');
48         $this->assertStringEqualsFile('/var/www/bookstack-restore/storage/uploads/test.txt', 'hello-storage-uploads');
49         $this->assertStringEqualsFile('/var/www/bookstack-restore/themes/test.txt', 'hello-themes');
50         $env = file_get_contents('/var/www/bookstack-restore/.env');
51         $this->assertStringContainsString('APP_KEY=abc123', $env);
52         $this->assertStringContainsString('APP_URL=https://example.com', $env);
53
54         $mysql->query("DROP TABLE zz_testing;");
55         exec('rm -rf /var/www/bookstack-restore');
56     }
57
58     public function test_command_fails_on_zip_with_no_expected_contents()
59     {
60         $zipFile = $this->buildZip(function (\ZipArchive $zip) {
61             $zip->addFromString('spaghetti', "Hello world!");
62         });
63
64         chdir('/var/www/bookstack');
65
66         $result = $this->runCommand('restore', [
67             'backup-zip' => $zipFile,
68         ]);
69
70         $result->assertErrorExit();
71         $result->assertStderrContains("Provided ZIP backup [{$zipFile}] does not have any expected restorable content.");
72     }
73
74     public function test_limited_restore_using_app_directory_option()
75     {
76         $zipFile = $this->buildZip(function (\ZipArchive $zip) {
77             $zip->addFromString('db.sql', "CREATE TABLE zz_testing (names varchar(255));");
78             $zip->addFromString('themes/hello.txt', "limited restore test!");
79         });
80
81         chdir('/home');
82
83         $result = $this->runCommand('restore', [
84             'backup-zip' => $zipFile,
85             '--app-directory' => '/var/www/bookstack'
86         ], ['yes']);
87
88         $result->assertSuccessfulExit();
89         $result->assertStdoutContains('❌ .env Config File');
90         $result->assertStdoutContains('✔ Themes Folder');
91         $result->assertStdoutContains('❌ Public File Uploads');
92         $result->assertStdoutContains('❌ Private File Uploads');
93         $result->assertStdoutContains('✔ Database Dump');
94         $this->assertStringEqualsFile('/var/www/bookstack/themes/hello.txt', 'limited restore test!');
95
96         unlink('/var/www/bookstack/themes/hello.txt');
97         $mysql = new mysqli('db', 'bookstack', 'bookstack', 'bookstack');
98         $mysql->query("DROP TABLE zz_testing;");
99     }
100
101     public function test_restore_with_symlinked_content_folders()
102     {
103         $zipFile = $this->buildZip(function (\ZipArchive $zip) {
104             $zip->addFromString('.env', "APP_KEY=abc123\nAPP_URL=https://example.com");
105             $zip->addFromString('public/uploads/test.txt', 'hello-public-uploads');
106             $zip->addFromString('storage/uploads/test.txt', 'hello-storage-uploads');
107             $zip->addFromString('themes/test.txt', 'hello-themes');
108         });
109
110         exec('cp -r /var/www/bookstack /var/www/bookstack-symlink-restore');
111         chdir('/var/www/bookstack-symlink-restore');
112         mkdir('/symlinks');
113
114         $symlinkPaths = ['public/uploads', 'storage/uploads', '.env', 'themes'];
115         foreach ($symlinkPaths as $path) {
116             $targetFile = str_replace('/', '-', $path);
117             $code = 0;
118             $output = null;
119             exec("mv /var/www/bookstack-symlink-restore/{$path} /symlinks/{$targetFile}", $output, $code);
120             exec("ln -s /symlinks/{$targetFile} /var/www/bookstack-symlink-restore/{$path}", $output, $code);
121             if ($code !== 0) {
122                 $this->fail("Error when setting up symlinks");
123             }
124         }
125
126         $result = $this->runCommand('restore', [
127             'backup-zip' => $zipFile,
128         ], ['yes', '1']);
129
130         $result->assertSuccessfulExit();
131
132         $this->assertStringEqualsFile('/var/www/bookstack-symlink-restore/public/uploads/test.txt', 'hello-public-uploads');
133         $this->assertStringEqualsFile('/var/www/bookstack-symlink-restore/storage/uploads/test.txt', 'hello-storage-uploads');
134         $this->assertStringEqualsFile('/var/www/bookstack-symlink-restore/themes/test.txt', 'hello-themes');
135
136         exec('rm -rf /var/www/bookstack-symlink-restore');
137     }
138
139     protected function buildZip(callable $builder): string
140     {
141         $zipFile = tempnam(sys_get_temp_dir(), 'cli-test');
142         $testZip = new \ZipArchive('');
143         $testZip->open($zipFile);
144         $builder($testZip);
145         $testZip->close();
146
147         return $zipFile;
148     }
149 }