markTestSkipped('CactiSecureHeaders is present in this runtime; the delegation path is covered by the isolated-process test.'); } expect(plugin_thold_csp_nonce())->toBe(''); }); test('csp nonce helper is declared to return a string', function () { $ref = new ReflectionFunction('plugin_thold_csp_nonce'); expect((string) $ref->getReturnType())->toBe('string'); }); test('csp nonce delegates to CactiSecureHeaders when the class is available', function () { $wrapper = realpath(__DIR__ . '/../../includes/functions.php'); expect($wrapper)->not->toBeFalse(); // includes/functions.php loads without a running Cacti, but hand the child the // unit bootstrap too so any Cacti stubs it might reference exist at load time. $bootstrap = realpath(__DIR__ . '/../bootstrap-unit.php'); // Run in a clean child process so the double never leaks into the rest // of the suite and the delegation branch is genuinely invoked. $script = <<<'CHILD' >>"; CHILD; $tmp = tempnam(sys_get_temp_dir(), 'csp_'); expect($tmp)->not->toBeFalse(); try { file_put_contents($tmp, $script); $command = escapeshellarg(PHP_BINARY) . ' ' . escapeshellarg($tmp) . ' ' . escapeshellarg($wrapper) . ' ' . escapeshellarg($bootstrap === false ? '' : $bootstrap); $output = shell_exec($command); expect($output)->not->toBeNull(); preg_match('/<<<(.*)>>>/s', (string) $output, $matches); expect($matches)->toHaveKey(1); expect($matches[1])->toBe(' nonce="pest-controlled-double"'); } finally { @unlink($tmp); } });