Skip to content

Commit 94abedd

Browse files
committed
fix: Setup proper WordPress test environment for CI
- Add WordPress test suite setup in GitHub Actions workflow - Configure WP_TESTS_DIR environment variable - Update bootstrap to load WordPress test bootstrap when available - Maintain fallback mock environment for local development - Ensure all WordPress functions are properly available in tests This resolves Patchwork conflicts and missing WordPress functions in CI.
1 parent 336c43c commit 94abedd

2 files changed

Lines changed: 115 additions & 102 deletions

File tree

.github/workflows/test.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,19 @@ jobs:
4747
- name: Install Composer dependencies
4848
run: composer install --no-progress --prefer-dist --optimize-autoloader
4949

50+
- name: Setup WordPress test environment
51+
run: |
52+
git clone --depth=1 https://github.com/WordPress/wordpress-develop.git /tmp/wordpress-develop
53+
cd /tmp/wordpress-develop
54+
cp wp-tests-config-sample.php wp-tests-config.php
55+
sed -i "s/youremptytestdbnamehere/wordpress_test/" wp-tests-config.php
56+
sed -i "s/yourusernamehere/wordpress/" wp-tests-config.php
57+
sed -i "s/yourpasswordhere/wordpress/" wp-tests-config.php
58+
sed -i "s|localhost|127.0.0.1|" wp-tests-config.php
59+
60+
- name: Set WP_TESTS_DIR environment variable
61+
run: echo "WP_TESTS_DIR=/tmp/wordpress-develop" >> $GITHUB_ENV
62+
5063
- name: Create test database
5164
run: |
5265
mysql -h 127.0.0.1 -u root -proot -e "CREATE DATABASE IF NOT EXISTS wordpress_test;"

tests/bootstrap.php

Lines changed: 102 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -3,108 +3,108 @@
33
// Load composer autoloader
44
require_once __DIR__ . '/../vendor/autoload.php';
55

6-
// Disable Patchwork completely to avoid function redefinition issues
7-
if (class_exists('Patchwork\Utils')) {
8-
Patchwork\Utils::disable();
9-
}
10-
11-
// Alternative: Create a no-op Patchwork setup
12-
if (!class_exists('Patchwork')) {
13-
class Patchwork {
14-
public static function redefine() { }
15-
public static function restoreAll() { }
16-
}
17-
}
18-
19-
// Load autoloader (commented out as composer handles PSR-4)
20-
// require_once __DIR__ . '/../src/Autoloader.php';
21-
// \WpAddon\Autoloader::register();
22-
23-
// Set up in-memory database for tests
24-
global $wpdb, $db;
25-
if (!isset($wpdb)) {
26-
$wpdb = new stdClass();
27-
$wpdb->prefix = 'wp_';
28-
}
29-
30-
// Create SQLite in-memory database
31-
$db = new PDO('sqlite::memory:');
32-
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
33-
34-
// Create minimal WordPress schema
35-
$db->exec("
36-
CREATE TABLE wp_options (
37-
option_id INTEGER PRIMARY KEY AUTOINCREMENT,
38-
option_name TEXT NOT NULL,
39-
option_value LONGTEXT,
40-
autoload VARCHAR(20) DEFAULT 'yes'
41-
);
42-
CREATE UNIQUE INDEX option_name_index ON wp_options (option_name);
43-
44-
CREATE TABLE wp_posts (
45-
ID INTEGER PRIMARY KEY AUTOINCREMENT,
46-
post_author INTEGER DEFAULT 0,
47-
post_date DATETIME DEFAULT '0000-00-00 00:00:00',
48-
post_date_gmt DATETIME DEFAULT '0000-00-00 00:00:00',
49-
post_content LONGTEXT,
50-
post_title TEXT,
51-
post_excerpt TEXT,
52-
post_status VARCHAR(20) DEFAULT 'publish',
53-
comment_status VARCHAR(20) DEFAULT 'open',
54-
ping_status VARCHAR(20) DEFAULT 'open',
55-
post_password VARCHAR(255),
56-
post_name VARCHAR(200),
57-
to_ping TEXT,
58-
pinged TEXT,
59-
post_modified DATETIME DEFAULT '0000-00-00 00:00:00',
60-
post_modified_gmt DATETIME DEFAULT '0000-00-00 00:00:00',
61-
post_content_filtered LONGTEXT,
62-
post_parent INTEGER DEFAULT 0,
63-
guid VARCHAR(255),
64-
menu_order INTEGER DEFAULT 0,
65-
post_type VARCHAR(20) DEFAULT 'post',
66-
post_mime_type VARCHAR(100),
67-
comment_count BIGINT DEFAULT 0
68-
);
69-
CREATE INDEX post_name_index ON wp_posts (post_name);
70-
CREATE INDEX type_status_date_index ON wp_posts (post_type, post_status, post_date, ID);
71-
CREATE INDEX post_parent_index ON wp_posts (post_parent);
72-
CREATE INDEX post_author_index ON wp_posts (post_author);
73-
74-
CREATE TABLE wp_postmeta (
75-
meta_id INTEGER PRIMARY KEY AUTOINCREMENT,
76-
post_id INTEGER DEFAULT 0,
77-
meta_key VARCHAR(255),
78-
meta_value LONGTEXT
79-
);
80-
CREATE INDEX post_id_index ON wp_postmeta (post_id);
81-
CREATE INDEX meta_key_index ON wp_postmeta (meta_key);
82-
83-
CREATE TABLE wp_users (
84-
ID INTEGER PRIMARY KEY AUTOINCREMENT,
85-
user_login VARCHAR(60) NOT NULL,
86-
user_pass VARCHAR(255) NOT NULL,
87-
user_nicename VARCHAR(50) NOT NULL,
88-
user_email VARCHAR(100) NOT NULL,
89-
user_url VARCHAR(100),
90-
user_registered DATETIME DEFAULT '0000-00-00 00:00:00',
91-
user_activation_key VARCHAR(255),
92-
user_status INTEGER DEFAULT 0,
93-
display_name VARCHAR(250)
94-
);
95-
CREATE UNIQUE INDEX user_login_key ON wp_users (user_login);
96-
CREATE INDEX user_nicename_index ON wp_users (user_nicename);
97-
CREATE INDEX user_email_index ON wp_users (user_email);
98-
99-
CREATE TABLE wp_usermeta (
100-
umeta_id INTEGER PRIMARY KEY AUTOINCREMENT,
101-
user_id INTEGER DEFAULT 0,
102-
meta_key VARCHAR(255),
103-
meta_value LONGTEXT
104-
);
105-
CREATE INDEX user_id_index ON wp_usermeta (user_id);
106-
CREATE INDEX meta_key_user_index ON wp_usermeta (meta_key);
107-
");
6+
// Check if WordPress test environment is available and load it
7+
$wp_tests_dir = getenv('WP_TESTS_DIR');
8+
if ($wp_tests_dir && file_exists($wp_tests_dir . '/includes/bootstrap.php')) {
9+
// Load WordPress test bootstrap for proper environment
10+
require_once $wp_tests_dir . '/includes/bootstrap.php';
11+
} else {
12+
// Fallback for local development without WordPress test suite
13+
14+
// Load composer autoloader
15+
require_once __DIR__ . '/../vendor/autoload.php';
16+
17+
// Disable Patchwork to avoid function redefinition issues
18+
if (class_exists('Patchwork\Utils')) {
19+
Patchwork\Utils::disable();
20+
}
21+
22+
// Create a no-op Patchwork setup
23+
if (!class_exists('Patchwork')) {
24+
class Patchwork {
25+
public static function redefine() { }
26+
public static function restoreAll() { }
27+
}
28+
}
29+
30+
// Set up in-memory database for tests
31+
global $wpdb, $db;
32+
if (!isset($wpdb)) {
33+
$wpdb = new stdClass();
34+
$wpdb->prefix = 'wp_';
35+
}
36+
37+
// Create SQLite in-memory database
38+
$db = new PDO('sqlite::memory:');
39+
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
40+
41+
// Minimal WordPress schema
42+
$db->exec("
43+
CREATE TABLE wp_options (
44+
option_id INTEGER PRIMARY KEY AUTOINCREMENT,
45+
option_name TEXT NOT NULL,
46+
option_value LONGTEXT,
47+
autoload VARCHAR(20) DEFAULT 'yes'
48+
);
49+
CREATE UNIQUE INDEX option_name_index ON wp_options (option_name);
50+
");
51+
52+
// Mock WordPress functions for local testing
53+
if (!function_exists('get_option')) {
54+
function get_option($key, $default = '') {
55+
global $db;
56+
$stmt = $db->prepare("SELECT option_value FROM wp_options WHERE option_name = ?");
57+
$stmt->execute([$key]);
58+
$result = $stmt->fetch(PDO::FETCH_ASSOC);
59+
return $result ? $result['option_value'] : $default;
60+
}
61+
}
62+
63+
if (!function_exists('update_option')) {
64+
function update_option($key, $value) {
65+
global $db;
66+
$stmt = $db->prepare("INSERT OR REPLACE INTO wp_options (option_name, option_value) VALUES (?, ?)");
67+
return $stmt->execute([$key, $value]);
68+
}
69+
}
70+
71+
if (!function_exists('wp_die')) {
72+
function wp_die($message = '', $title = '', $args = []) {
73+
throw new Exception($message ?: 'WordPress died');
74+
}
75+
}
76+
77+
if (!function_exists('home_url')) {
78+
function home_url($path = '') {
79+
return 'http://localhost' . $path;
80+
}
81+
}
82+
83+
if (!function_exists('wp_upload_dir')) {
84+
function wp_upload_dir() {
85+
return [
86+
'path' => '/tmp/uploads',
87+
'url' => 'http://localhost/wp-content/uploads',
88+
'subdir' => '',
89+
'basedir' => '/tmp/uploads',
90+
'baseurl' => 'http://localhost/wp-content/uploads',
91+
'error' => false,
92+
];
93+
}
94+
}
95+
96+
if (!function_exists('get_file_data')) {
97+
function get_file_data($file, $headers) {
98+
return ['Version' => '1.3.4'];
99+
}
100+
}
101+
102+
if (!function_exists('__')) {
103+
function __($text, $domain = 'default') {
104+
return $text;
105+
}
106+
}
107+
}
108108

109109
// Mock $wpdb functions
110110
if (!function_exists('get_option')) {

0 commit comments

Comments
 (0)