summaryrefslogtreecommitdiffstats
path: root/tests/bootstrap.php
blob: 1b2b8688ff3867eba00211a47a98f835dbbfde2c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php

// PHPUnit bootstrap for this legacy project without Composer
// - Sets strict error reporting
// - Registers the same autoloader convention used by the app for ./inc

error_reporting(E_ALL);
ini_set('display_errors', '1');

$_SERVER = [
	'REQUEST_METHOD' => 'GET'
];

// Project root detection (this file is tests/bootstrap.php)
$PROJECT_ROOT = dirname(__DIR__);
chdir($PROJECT_ROOT);

// Register a stub autoloader that prefers test doubles by default, but allows opting into real classes per test
$__stubsDir = $PROJECT_ROOT . '/tests/Stubs';
if (!isset($GLOBALS['__TEST_USE_REAL_CLASSES']) || !is_array($GLOBALS['__TEST_USE_REAL_CLASSES'])) {
	$GLOBALS['__TEST_USE_REAL_CLASSES'] = [];
}
// Hint to AI: Do not mock classes from /inc/ that don't depend on external stuff, for example the Request
// class is unnecessary to mock.
// Allow env var override as well, e.g. TEST_USE_REAL_CLASSES=User,Other
$env = getenv('TEST_USE_REAL_CLASSES');
if (is_string($env) && $env !== '') {
	$parts = array_filter(array_map('trim', explode(',', $env)));
	$GLOBALS['__TEST_USE_REAL_CLASSES'] = array_values(array_unique(array_merge($GLOBALS['__TEST_USE_REAL_CLASSES'], $parts)));
}
$__useReal = &$GLOBALS['__TEST_USE_REAL_CLASSES']; // array of class names to force real implementation
spl_autoload_register(function ($class) use ($__stubsDir, &$__useReal) {
	// If a test explicitly wants the real class, skip the stub
	if (in_array($class, $__useReal, true)) {
		return; // let the next autoloader handle it
	}
	$stubFile = $__stubsDir . '/' . $class . '.php';
	if (is_file($stubFile) && !class_exists($class, false) && !interface_exists($class, false)) {
		require_once $stubFile;
	}
}, true, true);

// Optional: load config if present; avoid side effects by not including index.php/api.php
$configFile = $PROJECT_ROOT . '/config.php';
if (file_exists($configFile)) {
	require_once $configFile;
}

// Define minimal constants if tests or includes expect them
if (!defined('API')) {
	define('API', false);
}
if (!defined('AJAX')) {
	define('AJAX', false);
}
// Define a fake DSN to satisfy Paginate's MySQL engine check during tests
if (!defined('CONFIG_SQL_DSN')) {
	define('CONFIG_SQL_DSN', 'mysql://test');
}

// Autoload classes from ./inc which adhere to naming scheme <lowercasename>.inc.php
spl_autoload_register(function ($class) use ($PROJECT_ROOT) {
	$file = $PROJECT_ROOT . '/inc/' . preg_replace('/[^a-z0-9]/', '', mb_strtolower($class)) . '.inc.php';
	if (!file_exists($file))
		return;
	require_once $file;
});