clqms-be/tests/unit/Rule/RuleDefModelTest.php
root 2bcdf09b55 chore: repo-wide normalization + rules test coverage
Normalize formatting/line endings across configs, controllers, models, tests, and OpenAPI specs.

Update rule expression/rule engine implementation and remove obsolete RuleAction controller/model.

Add unit tests for rule expression syntax and multi-action behavior, and include docs updates.
2026-03-16 07:24:50 +07:00

272 lines
8.8 KiB
PHP

<?php
namespace Tests\Unit\Rule;
use App\Models\Rule\RuleDefModel;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
class RuleDefModelTest extends CIUnitTestCase
{
use DatabaseTestTrait;
protected $model;
protected $seed = \App\Database\Seeds\TestSeeder::class;
protected function setUp(): void
{
parent::setUp();
$this->model = new RuleDefModel();
}
/**
* Test that getActiveByEvent returns empty array when TestSiteID is null
* This ensures rules are standalone and must be explicitly included by test
*/
public function testGetActiveByEventReturnsEmptyWithoutTestSiteID(): void
{
$rules = $this->model->getActiveByEvent('test_created', null);
$this->assertIsArray($rules);
$this->assertEmpty($rules);
}
/**
* Test that a rule can be linked to multiple tests
*/
public function testRuleCanBeLinkedToMultipleTests(): void
{
$db = \Config\Database::connect();
// Get two existing tests
$tests = $db->table('testdefsite')
->where('EndDate', null)
->limit(2)
->get()
->getResultArray();
if (count($tests) < 2) {
$this->markTestSkipped('Need at least 2 tests available in testdefsite table');
}
$testSiteID1 = (int) $tests[0]['TestSiteID'];
$testSiteID2 = (int) $tests[1]['TestSiteID'];
// Create a rule
$ruleData = [
'RuleCode' => 'MULTI_TEST_RULE',
'RuleName' => 'Multi Test Rule',
'EventCode' => 'test_created',
'ConditionExpr' => 'order["InternalOID"] > 0',
'CreateDate' => date('Y-m-d H:i:s'),
];
$ruleID = $this->model->insert($ruleData, true);
$this->assertNotFalse($ruleID);
// Link rule to both tests
$this->model->linkTest($ruleID, $testSiteID1);
$this->model->linkTest($ruleID, $testSiteID2);
// Verify rule is returned for both test sites
$rules1 = $this->model->getActiveByEvent('test_created', $testSiteID1);
$this->assertNotEmpty($rules1);
$this->assertCount(1, $rules1);
$this->assertEquals($ruleID, $rules1[0]['RuleID']);
$rules2 = $this->model->getActiveByEvent('test_created', $testSiteID2);
$this->assertNotEmpty($rules2);
$this->assertCount(1, $rules2);
$this->assertEquals($ruleID, $rules2[0]['RuleID']);
// Cleanup
$this->model->delete($ruleID);
}
/**
* Test that rules only work when explicitly linked to a test
*/
public function testRulesOnlyWorkWhenExplicitlyLinked(): void
{
$db = \Config\Database::connect();
// Get an existing test
$test = $db->table('testdefsite')
->where('EndDate', null)
->limit(1)
->get()
->getRowArray();
if (!$test) {
$this->markTestSkipped('No tests available in testdefsite table');
}
$testSiteID = (int) $test['TestSiteID'];
// Create a rule (not linked to any test yet)
$ruleData = [
'RuleCode' => 'UNLINKED_RULE',
'RuleName' => 'Unlinked Test Rule',
'EventCode' => 'test_created',
'ConditionExpr' => 'true',
'CreateDate' => date('Y-m-d H:i:s'),
];
$ruleID = $this->model->insert($ruleData, true);
$this->assertNotFalse($ruleID);
// Verify rule is NOT returned when not linked
$rules = $this->model->getActiveByEvent('test_created', $testSiteID);
$this->assertEmpty($rules);
// Now link the rule
$this->model->linkTest($ruleID, $testSiteID);
// Verify rule is now returned
$rules = $this->model->getActiveByEvent('test_created', $testSiteID);
$this->assertNotEmpty($rules);
$this->assertCount(1, $rules);
// Cleanup
$this->model->delete($ruleID);
}
/**
* Test that unlinking a test removes the rule for that test
*/
public function testUnlinkingTestRemovesRule(): void
{
$db = \Config\Database::connect();
// Get two existing tests
$tests = $db->table('testdefsite')
->where('EndDate', null)
->limit(2)
->get()
->getResultArray();
if (count($tests) < 2) {
$this->markTestSkipped('Need at least 2 tests available in testdefsite table');
}
$testSiteID1 = (int) $tests[0]['TestSiteID'];
$testSiteID2 = (int) $tests[1]['TestSiteID'];
// Create a rule and link to both tests
$ruleData = [
'RuleCode' => 'UNLINK_TEST',
'RuleName' => 'Unlink Test Rule',
'EventCode' => 'test_created',
'ConditionExpr' => 'true',
'CreateDate' => date('Y-m-d H:i:s'),
];
$ruleID = $this->model->insert($ruleData, true);
$this->model->linkTest($ruleID, $testSiteID1);
$this->model->linkTest($ruleID, $testSiteID2);
// Verify rule is returned for both
$this->assertNotEmpty($this->model->getActiveByEvent('test_created', $testSiteID1));
$this->assertNotEmpty($this->model->getActiveByEvent('test_created', $testSiteID2));
// Unlink from first test
$this->model->unlinkTest($ruleID, $testSiteID1);
// Verify rule is NOT returned for first test but still for second
$this->assertEmpty($this->model->getActiveByEvent('test_created', $testSiteID1));
$this->assertNotEmpty($this->model->getActiveByEvent('test_created', $testSiteID2));
// Cleanup
$this->model->delete($ruleID);
}
/**
* Test that deleted (soft deleted) rules are not returned
*/
public function testDeletedRulesAreNotReturned(): void
{
$db = \Config\Database::connect();
$test = $db->table('testdefsite')
->where('EndDate', null)
->limit(1)
->get()
->getRowArray();
if (!$test) {
$this->markTestSkipped('No tests available in testdefsite table');
}
$testSiteID = (int) $test['TestSiteID'];
// Create a rule and link it
$ruleData = [
'RuleCode' => 'DELETED_RULE',
'RuleName' => 'Deleted Test Rule',
'EventCode' => 'test_created',
'ConditionExpr' => 'true',
'CreateDate' => date('Y-m-d H:i:s'),
];
$ruleID = $this->model->insert($ruleData, true);
$this->assertNotFalse($ruleID);
$this->model->linkTest($ruleID, $testSiteID);
// Verify rule is returned
$rules = $this->model->getActiveByEvent('test_created', $testSiteID);
$this->assertNotEmpty($rules);
// Soft delete the rule
$this->model->delete($ruleID);
// Verify deleted rule is NOT returned
$rules = $this->model->getActiveByEvent('test_created', $testSiteID);
$this->assertEmpty($rules);
}
/**
* Test getting linked tests for a rule
*/
public function testGetLinkedTests(): void
{
$db = \Config\Database::connect();
// Get two existing tests
$tests = $db->table('testdefsite')
->where('EndDate', null)
->limit(2)
->get()
->getResultArray();
if (count($tests) < 2) {
$this->markTestSkipped('Need at least 2 tests available');
}
$testSiteID1 = (int) $tests[0]['TestSiteID'];
$testSiteID2 = (int) $tests[1]['TestSiteID'];
// Create a rule
$ruleData = [
'RuleCode' => 'LINKED_TESTS',
'RuleName' => 'Linked Tests Rule',
'EventCode' => 'test_created',
'ConditionExpr' => 'true',
'CreateDate' => date('Y-m-d H:i:s'),
];
$ruleID = $this->model->insert($ruleData, true);
$this->model->linkTest($ruleID, $testSiteID1);
$this->model->linkTest($ruleID, $testSiteID2);
// Get linked tests
$linkedTests = $this->model->getLinkedTests($ruleID);
$this->assertCount(2, $linkedTests);
$this->assertContains($testSiteID1, $linkedTests);
$this->assertContains($testSiteID2, $linkedTests);
// Cleanup
$this->model->delete($ruleID);
}
}