users_file = sys_get_temp_dir() . '/bicycle_toolbar_users_' . uniqid('', true) . '.php'; file_put_contents($this->users_file, ' ['password' => password_hash('x', PASSWORD_DEFAULT), 'role' => 'admin'], 'bob' => ['password' => password_hash('x', PASSWORD_DEFAULT), 'role' => 'manager'], ], true) . ';'); Config::set('auth', ['driver' => 'file', 'users_file' => $this->users_file, 'session_key' => 'auth_user']); // Другие тесты пишут в этот же статический реестр, если есть живое подключение к БД. Profiler::reset(); } protected function tearDown(): void { unlink($this->users_file); Session::instance()->destroy(); Profiler::reset(); foreach ([Session::class, Auth::class] as $class) { $ref = new ReflectionClass($class); $prop = $ref->getProperty($class === Session::class ? 'instances' : '_instances'); $prop->setAccessible(true); $prop->setValue(null, []); } $ref = new ReflectionClass(Config::class); $prop = $ref->getProperty('config'); $prop->setAccessible(true); $prop->setValue(null, null); $ref = new ReflectionClass(ProfilerToolbar::class); $prop = $ref->getProperty('_custom'); $prop->setAccessible(true); $prop->setValue(null, []); $ref = new ReflectionClass(Database::class); $prop = $ref->getProperty('_instances'); $prop->setAccessible(true); $prop->setValue(null, []); } public function testReturnsEmptyStringForGuest(): void { $this->assertSame('', ProfilerToolbar::render()); } public function testReturnsEmptyStringForNonAdminRole(): void { Session::instance()->set('auth_user', 'bob'); $this->assertSame('', ProfilerToolbar::render()); } public function testRendersPanelForAdmin(): void { Session::instance()->set('auth_user', 'admin'); $html = ProfilerToolbar::render(); $this->assertStringContainsString('Profiler', $html); $this->assertStringContainsString('SQL', $html); } public function testIncludesProfilerEntries(): void { Session::instance()->set('auth_user', 'admin'); Profiler::log('SELECT * FROM users WHERE id = ?', [42], 1.23); $html = ProfilerToolbar::render(); $this->assertStringContainsString('SELECT * FROM users WHERE id = ?', $html); $this->assertStringContainsString('42', $html); } public function testHasVarsFilesAndRouteTabs(): void { Session::instance()->set('auth_user', 'admin'); $html = ProfilerToolbar::render(); $this->assertStringContainsString('Vars', $html); $this->assertStringContainsString('Files', $html); $this->assertStringContainsString('Route', $html); } public function testVarsTabMasksSensitiveKeys(): void { Session::instance()->set('auth_user', 'admin'); $_POST['password'] = 'super-secret'; $html = ProfilerToolbar::render(); $this->assertStringNotContainsString('super-secret', $html); $this->assertStringContainsString('***', $html); unset($_POST['password']); } public function testExplainShownForRealSelect(): void { try { Database::instance()->exec('DROP TABLE IF EXISTS profiler_toolbar_test'); Database::instance()->exec('CREATE TABLE profiler_toolbar_test (id INT PRIMARY KEY)'); } catch (MyException $e) { $this->markTestSkipped('Нет живого подключения к MariaDB: ' . $e->getMessage()); } Session::instance()->set('auth_user', 'admin'); Database::instance()->query('SELECT * FROM profiler_toolbar_test WHERE id = ?', [1]); $html = ProfilerToolbar::render(); Database::instance()->exec('DROP TABLE IF EXISTS profiler_toolbar_test'); $this->assertStringContainsString('ptb-explain', $html); $this->assertStringContainsString('select_type', $html); } public function testExplainSkippedForNonSelect(): void { Session::instance()->set('auth_user', 'admin'); Profiler::log('DELETE FROM users WHERE id = ?', [1], 0.5); $html = ProfilerToolbar::render(); // 'ptb-explain' сам по себе — ещё и имя CSS-класса в