Files
2meet-data-optimizer/tests/unit/MemberFields/MemberFieldsRegistrationTest.php
T
wpdev a0847a27bf fix(audit,sso): audit 表補 group_name/action 欄 + 註冊 Audit_Logger + known_login_ips(A11/A12/A14)
- wpdo_audit CREATE 補 group_name varchar(50) 與 action varchar(20):
  TMDO_Audit_Logger::write_row() 一直在寫這兩個 key,表卻沒有該欄位。
  SCHEMA_VERSION 2.0.0 → 2.1.0 觸發既有站台 dbDelta ALTER;主檔與兩個
  test bootstrap 的 TMDO_DB_VERSION 同步(BackCompatTest 守門要求一致)。
- TMDO_Core::run() 註冊 TMDO_Audit_Logger::init():先前完全沒掛,
  wpdo_after_write / wpdo_after_delete 的稽核監聽器形同不存在。
- register_sso_group() 補 known_login_ips(A v3.4.4):2meet-spoke-sso 的
  TMSO_Login_Notify 以 set_entity 寫此欄,未註冊時降級落 wp_usermeta。
  對應測試改為 test_sso_group_has_eight_fields。

unit 379 / integration 398 GREEN

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
2026-07-31 05:16:33 +08:00

205 lines
8.3 KiB
PHP

<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
/**
* Unit tests for WPDO_Member_Fields entity group registration.
*
* Verifies that register_entity_fields() correctly registers all four
* user groups with the expected field counts, types, and attributes.
*/
class MemberFieldsRegistrationTest extends TestCase {
protected function setUp(): void {
// Load the class under test if not already loaded.
if ( ! class_exists( 'WPDO_Member_Fields' ) ) {
require_once WPDO_PLUGIN_DIR . 'includes/integrations/class-tmdo-member-fields.php';
}
if ( ! class_exists( 'WPDO_Adapter_User' ) ) {
require_once WPDO_PLUGIN_DIR . 'includes/adapters/class-tmdo-adapter-user.php';
}
// Reset Entity Registry and register the user adapter.
WPDO_Entity_Registry::init();
WPDO_Entity_Registry::register_adapter( 'user', new WPDO_Adapter_User() );
}
// ── Group presence ───────────────────────────────────────────────────────
public function test_register_entity_fields_returns_early_without_entity_registry(): void {
// Class_exists('WPDO_Entity_Registry') will be true here, so we just
// confirm calling the method twice (dedup guard) returns false the 2nd time.
WPDO_Member_Fields::register_entity_fields();
// Second call: groups already registered — register_group() returns false (dedup).
// No assertion needed: simply must not throw.
$this->assertTrue( true );
}
public function test_all_four_groups_are_registered(): void {
WPDO_Member_Fields::register_entity_fields();
foreach ( array( 'membership', 'activity', 'profile', 'sso' ) as $group ) {
$fields = WPDO_Entity_Registry::get_group_fields( 'user', $group );
$this->assertNotEmpty( $fields, "Group '{$group}' should have registered fields." );
}
}
// ── membership group ─────────────────────────────────────────────────────
public function test_membership_group_has_six_fields(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'membership' );
$this->assertCount( 6, $fields );
}
public function test_membership_level_is_enum_with_five_options(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'membership' );
$level = $this->find_field( $fields, 'membership_level' );
$this->assertNotNull( $level );
$this->assertSame( 'enum', $level['type'] );
$this->assertCount( 5, $level['options'] );
$this->assertContains( 'gold', $level['options'] );
$this->assertContains( 'platinum', $level['options'] );
}
public function test_membership_level_is_searchable(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'membership' );
$level = $this->find_field( $fields, 'membership_level' );
$this->assertTrue( (bool) $level['searchable'] );
}
public function test_points_balance_is_integer_searchable(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'membership' );
$field = $this->find_field( $fields, 'points_balance' );
$this->assertSame( 'integer', $field['type'] );
$this->assertTrue( (bool) $field['searchable'] );
$this->assertSame( 0, $field['default'] );
}
public function test_membership_expires_at_is_datetime_searchable(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'membership' );
$field = $this->find_field( $fields, 'membership_expires_at' );
$this->assertSame( 'datetime', $field['type'] );
$this->assertTrue( (bool) $field['searchable'] );
}
// ── activity group ───────────────────────────────────────────────────────
public function test_activity_group_has_six_fields(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'activity' );
$this->assertCount( 6, $fields );
}
public function test_login_count_has_integer_type_and_zero_default(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'activity' );
$field = $this->find_field( $fields, 'login_count' );
$this->assertSame( 'integer', $field['type'] );
$this->assertSame( 0, $field['default'] );
}
public function test_account_flags_is_integer(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'activity' );
$field = $this->find_field( $fields, 'account_flags' );
$this->assertSame( 'integer', $field['type'] );
}
// ── profile group ────────────────────────────────────────────────────────
public function test_profile_group_has_five_fields(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'profile' );
$this->assertCount( 5, $fields );
}
public function test_specialties_is_json_type(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'profile' );
$field = $this->find_field( $fields, 'specialties' );
$this->assertSame( 'json', $field['type'] );
}
public function test_display_name_custom_is_fulltext_searchable(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'profile' );
$field = $this->find_field( $fields, 'display_name_custom' );
$this->assertTrue( (bool) $field['searchable'] );
$this->assertTrue( (bool) $field['fulltext'] );
}
// ── sso group ────────────────────────────────────────────────────────────
public function test_sso_group_has_eight_fields(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'sso' );
// v3.4.4: known_login_ips registered (was leaking to wp_usermeta via set_entity).
$this->assertCount( 8, $fields );
$this->assertNotNull( $this->find_field( $fields, 'known_login_ips' ) );
}
public function test_hub_global_user_id_is_searchable(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'sso' );
$field = $this->find_field( $fields, 'hub_global_user_id' );
$this->assertTrue( (bool) $field['searchable'] );
}
public function test_token_expires_at_is_datetime_searchable(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'sso' );
$field = $this->find_field( $fields, 'token_expires_at' );
$this->assertSame( 'datetime', $field['type'] );
$this->assertTrue( (bool) $field['searchable'] );
}
public function test_refresh_token_enc_is_textarea(): void {
WPDO_Member_Fields::register_entity_fields();
$fields = WPDO_Entity_Registry::get_group_fields( 'user', 'sso' );
$field = $this->find_field( $fields, 'refresh_token_enc' );
$this->assertSame( 'textarea', $field['type'] );
}
// ── register() hooks add_action ──────────────────────────────────────────
public function test_register_hooks_wpdo_register_entity_fields(): void {
// add_action is a no-op stub in test bootstrap; just confirm no exception.
$this->assertNull( WPDO_Member_Fields::register() );
}
// ── helper ───────────────────────────────────────────────────────────────
/**
* Find a field definition by key within a fields array.
*
* @param array $fields Array of field definitions.
* @param string $key Meta key to find.
* @return array|null
*/
private function find_field( array $fields, string $key ): ?array {
foreach ( $fields as $field ) {
if ( $field['key'] === $key ) {
return $field;
}
}
return null;
}
}