feat: 实现TCP Server

This commit is contained in:
zimoyin
2026-03-02 21:59:43 +08:00
parent 043306819b
commit a79dfae57d
144 changed files with 15785 additions and 140 deletions
+142
View File
@@ -0,0 +1,142 @@
<?php
namespace tests\flow\nodes;
use tests\flow\TestCase;
use app\flow\nodes\DisinfectNode;
use app\flow\DbOperationType;
/**
* 消毒节点单元测试
*/
class DisinfectNodeTest extends TestCase
{
protected DisinfectNode $node;
protected function setUp(): void
{
$this->node = new DisinfectNode();
}
/**
* 测试节点名称和编码
*/
public function testNodeIdentity(): void
{
$this->assertEquals('消毒', $this->node->getName());
$this->assertEquals('消毒', $this->node->getCode());
}
/**
* 测试漂洗后可以刷消毒
*/
public function testCanHandleAfterRinse(): void
{
$context = $this->createContext([
'readerType' => '消毒',
'currentStep' => '漂洗',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试终末漂洗后禁止刷消毒
*/
public function testCanHandleAfterFinalRinse(): void
{
$context = $this->createContext([
'readerType' => '消毒',
'currentStep' => '终末漂洗',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试清洗后禁止直接刷消毒
*/
public function testCanHandleAfterWash(): void
{
$context = $this->createContext([
'readerType' => '消毒',
'currentStep' => '清洗',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试不能处理非消毒读卡器
*/
public function testCannotHandleNonDisinfectReader(): void
{
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => '漂洗',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试消毒后不能立即刷消毒
*/
public function testCannotHandleAfterDisinfect(): void
{
$context = $this->createContext([
'readerType' => '消毒',
'currentStep' => '消毒',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试处理流程
*/
public function testHandleProcess(): void
{
$context = $this->createContext([
'readerType' => '消毒',
'currentStep' => '漂洗',
]);
$result = $this->node->handle($context);
$this->assertSuccess($result);
$this->assertStep($result, '消毒');
$this->assertNotNull($result->getStepLastTime('消毒'));
}
/**
* 测试数据库操作标记
*/
public function testDatabaseOperationFlags(): void
{
$context = $this->createContext([
'readerType' => '消毒',
'currentStep' => '漂洗',
]);
$this->node->handle($context);
$this->assertTrue($context->needDatabaseOperation);
$this->assertEquals(DbOperationType::INSERT, $context->dbOperation);
}
/**
* 测试 WebSocket 通知标记
*/
public function testWebSocketNotifyFlag(): void
{
$context = $this->createContext([
'readerType' => '消毒',
'currentStep' => '漂洗',
]);
$this->node->handle($context);
$this->assertTrue($context->needWebSocketNotify);
}
}
+158
View File
@@ -0,0 +1,158 @@
<?php
namespace tests\flow\nodes;
use tests\flow\TestCase;
use app\flow\nodes\DryNode;
use app\flow\DbOperationType;
/**
* 干燥节点单元测试
*/
class DryNodeTest extends TestCase
{
protected DryNode $node;
protected function setUp(): void
{
$this->node = new DryNode();
}
/**
* 测试节点名称和编码
*/
public function testNodeIdentity(): void
{
$this->assertEquals('干燥', $this->node->getName());
$this->assertEquals('干燥', $this->node->getCode());
}
/**
* 测试终末漂洗后可以刷干燥
*/
public function testCanHandleAfterFinalRinse(): void
{
$context = $this->createContext([
'readerType' => '干燥',
'currentStep' => '终末漂洗',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试消毒后可以直接刷干燥(跳过终末漂洗)
*/
public function testCanHandleAfterDisinfect(): void
{
$context = $this->createContext([
'readerType' => '干燥',
'currentStep' => '消毒'
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试漂洗后不能直接刷干燥
*/
public function testCannotHandleAfterRinse(): void
{
$context = $this->createContext([
'readerType' => '干燥',
'currentStep' => '漂洗',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试不能处理非干燥读卡器
*/
public function testCannotHandleNonDryReader(): void
{
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => '终末漂洗',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试干燥后不能立即刷干燥
*/
public function testCannotHandleAfterDry(): void
{
$context = $this->createContext([
'readerType' => '干燥',
'currentStep' => '干燥',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试处理流程
*/
public function testHandleProcess(): void
{
$context = $this->createContext([
'readerType' => '干燥',
'currentStep' => '终末漂洗',
]);
$result = $this->node->handle($context);
$this->assertSuccess($result);
$this->assertStep($result, '干燥');
$this->assertNotNull($result->getStepLastTime('干燥'));
}
/**
* 测试数据库操作标记
*/
public function testDatabaseOperationFlags(): void
{
$context = $this->createContext([
'readerType' => '干燥',
'currentStep' => '终末漂洗',
]);
$this->node->handle($context);
$this->assertTrue($context->needDatabaseOperation);
$this->assertEquals(DbOperationType::INSERT, $context->dbOperation);
}
/**
* 测试 WebSocket 通知标记
*/
public function testWebSocketNotifyFlag(): void
{
$context = $this->createContext([
'readerType' => '干燥',
'currentStep' => '终末漂洗',
]);
$this->node->handle($context);
$this->assertTrue($context->needWebSocketNotify);
}
/**
* 测试保持现有批次号
*/
public function testKeepExistingBatchNo(): void
{
$context = $this->createContext([
'readerType' => '干燥',
'currentStep' => '终末漂洗',
'batchNo' => '202603031200000000010001',
]);
$this->node->handle($context);
$this->assertEquals('202603031200000000010001', $context->batchNo);
}
}
+202
View File
@@ -0,0 +1,202 @@
<?php
namespace tests\flow\nodes;
use tests\flow\TestCase;
use app\flow\nodes\EndNode;
use app\flow\DbOperationType;
/**
* 结束节点单元测试
*/
class EndNodeTest extends TestCase
{
protected EndNode $node;
protected function setUp(): void
{
$this->node = new EndNode();
}
/**
* 测试节点名称和编码
*/
public function testNodeIdentity(): void
{
$this->assertEquals('结束', $this->node->getName());
$this->assertEquals('结束', $this->node->getCode());
}
/**
* 测试干燥后可以刷结束
*/
public function testCanHandleAfterDry(): void
{
$context = $this->createContext([
'readerType' => '结束',
'currentStep' => '干燥',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试消毒后可以刷结束(跳过终末漂洗)
*/
public function testCanHandleAfterDisinfect(): void
{
$context = $this->createContext([
'readerType' => '结束',
'currentStep' => '消毒',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试终末漂洗后可以刷结束
*/
public function testCanHandleAfterFinalRinse(): void
{
$context = $this->createContext([
'readerType' => '结束',
'currentStep' => '终末漂洗',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试机洗后可以刷结束
*/
public function testCanHandleAfterMachineWash(): void
{
$context = $this->createContext([
'readerType' => '结束',
'currentStep' => '机洗',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试非结束读卡器不能处理
*/
public function testCannotHandleNonEndReader(): void
{
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => '干燥',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试清洗后不能直接刷结束
*/
public function testCannotHandleAfterWash(): void
{
$context = $this->createContext([
'readerType' => '结束',
'currentStep' => '清洗',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试漂洗后不能直接刷结束
*/
public function testCannotHandleAfterRinse(): void
{
$context = $this->createContext([
'readerType' => '结束',
'currentStep' => '漂洗',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试空步骤不能刷结束
*/
public function testCannotHandleWithEmptyStep(): void
{
$context = $this->createContext([
'readerType' => '结束',
'currentStep' => '',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试处理流程
*/
public function testHandleProcess(): void
{
$context = $this->createContext([
'readerType' => '结束',
'currentStep' => '干燥',
'batchNo' => 'BATCH001',
'actionStartTime' => date('Y-m-d H:i:s', time() - 600),
]);
$result = $this->node->handle($context);
$this->assertSuccess($result);
$this->assertStep($result, '结束');
$this->assertNotEmpty($result->actionEndTime);
}
/**
* 测试数据库操作标记(update 而非 insert
*/
public function testDatabaseOperationIsUpdate(): void
{
$context = $this->createContext([
'readerType' => '结束',
'currentStep' => '干燥',
'batchNo' => 'BATCH001',
]);
$this->node->handle($context);
$this->assertTrue($context->needDatabaseOperation);
$this->assertEquals(DbOperationType::INSERT, $context->dbOperation);
}
/**
* 测试 WebSocket 通知标记
*/
public function testWebSocketNotifyFlag(): void
{
$context = $this->createContext([
'readerType' => '结束',
'currentStep' => '干燥',
]);
$this->node->handle($context);
$this->assertTrue($context->needWebSocketNotify);
}
/**
* 测试 actionEndTime 被设置
*/
public function testActionEndTimeIsSet(): void
{
$context = $this->createContext([
'readerType' => '结束',
'currentStep' => '干燥',
]);
$before = date('Y-m-d H:i:s');
$this->node->handle($context);
$after = date('Y-m-d H:i:s');
$this->assertGreaterThanOrEqual($before, $context->actionEndTime);
$this->assertLessThanOrEqual($after, $context->actionEndTime);
}
}
+148
View File
@@ -0,0 +1,148 @@
<?php
namespace tests\flow\nodes;
use tests\flow\TestCase;
use app\flow\nodes\FinalRinseNode;
use app\flow\DbOperationType;
/**
* 终末漂洗节点单元测试
*/
class FinalRinseNodeTest extends TestCase
{
protected FinalRinseNode $node;
protected function setUp(): void
{
$this->node = new FinalRinseNode();
}
/**
* 测试消毒后可以刷终末漂洗
*/
public function testCanHandleAfterDisinfect(): void
{
$context = $this->createContext([
'readerType' => '终末漂洗',
'currentStep' => '消毒',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试机洗后可以刷终末漂洗(默认配置)
*/
public function testCanHandleAfterMachineWashByDefault(): void
{
$context = $this->createContext([
'readerType' => '终末漂洗',
'currentStep' => '机洗',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试禁用的节点不会处理任何请求(特殊医院配置)
*/
public function testCannotHandleAfterMachineWashWhenDisabled(): void
{
$node = new FinalRinseNode();
$node->setEnabled(false); // 禁用节点
$context = $this->createContext([
'readerType' => '终末漂洗',
'currentStep' => '机洗',
]);
// 禁用的节点不处理请求:handle 直接将上下文传递给下一节点,不更改 currentStep
$result = $node->handle($context);
$this->assertEquals('机洗', $result->currentStep); // 步骤不变
$this->assertFalse($result->needDatabaseOperation); // 不写库
}
/**
* 测试不能处理非终末漂洗读卡器
*/
public function testCannotHandleNonFinalRinseReader(): void
{
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => '消毒',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试处理流程
*/
public function testHandleProcess(): void
{
$context = $this->createContext([
'readerType' => '终末漂洗',
'currentStep' => '消毒',
]);
$result = $this->node->handle($context);
$this->assertSuccess($result);
$this->assertStep($result, '终末漂洗');
$this->assertNotNull($result->getStepLastTime('终末漂洗'));
}
/**
* 测试清洗后不能直接刷终末漂洗
*/
public function testCannotHandleAfterWash(): void
{
$context = $this->createContext([
'readerType' => '终末漂洗',
'currentStep' => '清洗',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试数据库操作标记
*/
public function testDatabaseOperationFlags(): void
{
$context = $this->createContext([
'readerType' => '终末漂洗',
'currentStep' => '消毒',
]);
$this->node->handle($context);
$this->assertTrue($context->needDatabaseOperation);
$this->assertEquals(DbOperationType::INSERT, $context->dbOperation);
}
/**
* 测试 WebSocket 通知标记
*/
public function testWebSocketNotifyFlag(): void
{
$context = $this->createContext([
'readerType' => '终末漂洗',
'currentStep' => '消毒',
]);
$this->node->handle($context);
$this->assertTrue($context->needWebSocketNotify);
}
/**
* 测试节点名称和编码
*/
public function testNodeIdentity(): void
{
$this->assertEquals('终末漂洗', $this->node->getName());
$this->assertEquals('终末漂洗', $this->node->getCode());
}
}
+196
View File
@@ -0,0 +1,196 @@
<?php
namespace tests\flow\nodes;
use tests\flow\TestCase;
use app\flow\nodes\MachineWashNode;
use app\flow\DbOperationType;
/**
* 机洗节点单元测试
*/
class MachineWashNodeTest extends TestCase
{
protected MachineWashNode $node;
protected function setUp(): void
{
$this->node = new MachineWashNode();
}
/**
* 测试节点名称和编码
*/
public function testNodeIdentity(): void
{
$this->assertEquals('机洗', $this->node->getName());
$this->assertEquals('机洗', $this->node->getCode());
}
/**
* 测试清洗后可以刷机洗
*/
public function testCanHandleAfterWash(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '清洗',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试漂洗后可以刷机洗
*/
public function testCanHandleAfterRinse(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '漂洗',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试消毒后可以刷机洗
*/
public function testCanHandleAfterDisinfect(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '消毒',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试步骤为空时可以刷机洗(新流程开始)
*/
public function testCanHandleWithEmptyStep(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试结束后可以刷机洗
*/
public function testCanHandleAfterEnd(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '结束',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试内镜取出后可以刷机洗
*/
public function testCanHandleAfterEndoscopeOut(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '内镜取出',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试非机洗读卡器不能处理
*/
public function testCannotHandleNonMachineWashReader(): void
{
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => '清洗',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试终末漂洗后不能刷机洗
*/
public function testCannotHandleAfterFinalRinse(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '终末漂洗',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试干燥后不能刷机洗
*/
public function testCannotHandleAfterDry(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '干燥',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试处理流程
*/
public function testHandleProcess(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '清洗',
'batchNo' => 'BATCH001',
]);
$result = $this->node->handle($context);
$this->assertSuccess($result);
$this->assertStep($result, '机洗');
$this->assertEquals('机洗', $result->processType);
$this->assertNotNull($result->getStepLastTime('机洗'));
}
/**
* 测试数据库操作标记
*/
public function testDatabaseOperationFlags(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '清洗',
]);
$this->node->handle($context);
$this->assertTrue($context->needDatabaseOperation);
$this->assertEquals(DbOperationType::INSERT, $context->dbOperation);
}
/**
* 测试 WebSocket 通知标记
*/
public function testWebSocketNotifyFlag(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '清洗',
]);
$this->node->handle($context);
$this->assertTrue($context->needWebSocketNotify);
}
}
+157
View File
@@ -0,0 +1,157 @@
<?php
namespace tests\flow\nodes;
use tests\flow\TestCase;
use app\flow\nodes\MorningWashNode;
/**
* 晨洗节点单元测试
*/
class MorningWashNodeTest extends TestCase
{
protected MorningWashNode $node;
protected function setUp(): void
{
$this->node = new MorningWashNode();
}
/**
* 测试节点名称和编码
*/
public function testNodeIdentity(): void
{
$this->assertEquals('晨洗', $this->node->getName());
$this->assertEquals('晨洗', $this->node->getCode());
}
/**
* 测试可以处理消毒读卡器(晨洗模式)
*/
public function testCanHandleDisinfectReaderForMorningWash(): void
{
$context = $this->createContext([
'readerType' => '消毒',
'currentStep' => '',
'needMorningWash' => true,
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试可以处理机洗读卡器(晨洗模式)
*/
public function testCanHandleMachineWashReaderForMorningWash(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '',
'needMorningWash' => true,
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试不需要晨洗时不能处理
*/
public function testCannotHandleWhenNoNeed(): void
{
$context = $this->createContext([
'readerType' => '晨洗',
'currentStep' => '',
'needMorningWash' => false,
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试非消毒/机洗读卡器不能处理晨洗
*/
public function testCannotHandleNonDisinfectMachineReader(): void
{
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => '',
'needMorningWash' => true,
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试已完成晨洗后不能再次处理
*/
public function testCannotHandleWhenAlreadyWashed(): void
{
$context = $this->createContext([
'readerType' => '晨洗',
'currentStep' => '晨洗',
'needMorningWash' => false,
'morningWashed' => true,
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试处理流程(消毒读卡器)
*/
public function testHandleProcessWithDisinfect(): void
{
$context = $this->createContext([
'readerType' => '消毒',
'currentStep' => '',
'needMorningWash' => true,
'endoscopeId' => '', // 避免触发 DB 查询
]);
$result = $this->node->handle($context);
$this->assertSuccess($result);
$this->assertEquals('清洗', $result->currentStep); // 晨洗后进入清洗步骤
$this->assertTrue($result->morningWashed);
$this->assertEquals('手工洗(晨洗)', $result->processType);
}
/**
* 测试处理流程(机洗读卡器)
*/
public function testHandleProcessWithMachineWash(): void
{
$context = $this->createContext([
'readerType' => '机洗',
'currentStep' => '',
'needMorningWash' => true,
'endoscopeId' => '', // 避免触发 DB 查询
]);
$result = $this->node->handle($context);
$this->assertSuccess($result);
$this->assertEquals('清洗', $result->currentStep);
$this->assertTrue($result->morningWashed);
$this->assertEquals('机洗(晨洗)', $result->processType);
}
/**
* 测试生成批次号
*/
public function testGenerateBatchNo(): void
{
$context = $this->createContext([
'readerType' => '消毒',
'currentStep' => '',
'needMorningWash' => true,
'endoscopeId' => '', // 避免触发 DB 查询
]);
$this->node->handle($context);
$this->assertNotEmpty($context->batchNo);
$this->assertTrue($context->needDatabaseOperation);
}
}
+163
View File
@@ -0,0 +1,163 @@
<?php
namespace tests\flow\nodes;
use tests\flow\TestCase;
use app\flow\nodes\RinseNode;
use app\flow\DbOperationType;
/**
* 漂洗节点单元测试
*/
class RinseNodeTest extends TestCase
{
protected RinseNode $node;
protected function setUp(): void
{
$this->node = new RinseNode();
// 确保每个测试时节点都是启用状态
$this->node->setEnabled(true);
}
/**
* 测试节点名称和编码
*/
public function testNodeIdentity(): void
{
$this->assertEquals('漂洗', $this->node->getName());
$this->assertEquals('漂洗', $this->node->getCode());
}
/**
* 测试清洗后可以刷漂洗
*/
public function testCanHandleAfterWash(): void
{
$context = $this->createContext([
'readerType' => '漂洗',
'currentStep' => '清洗',
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试非漂洗读卡器不能处理
*/
public function testCannotHandleNonRinseReader(): void
{
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => '清洗',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试消毒后不能刷漂洗
*/
public function testCannotHandleAfterDisinfect(): void
{
$context = $this->createContext([
'readerType' => '漂洗',
'currentStep' => '消毒',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试步骤为空时不能刷漂洗
*/
public function testCannotHandleWithEmptyStep(): void
{
$context = $this->createContext([
'readerType' => '漂洗',
'currentStep' => '',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试漂洗后不能立即再次漂洗
*/
public function testCannotHandleAfterRinse(): void
{
$context = $this->createContext([
'readerType' => '漂洗',
'currentStep' => '漂洗',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试处理流程
*/
public function testHandleProcess(): void
{
$context = $this->createContext([
'readerType' => '漂洗',
'currentStep' => '清洗',
'batchNo' => 'BATCH001',
]);
$result = $this->node->handle($context);
$this->assertSuccess($result);
$this->assertStep($result, '漂洗');
$this->assertNotNull($result->getStepLastTime('漂洗'));
}
/**
* 测试数据库操作标记
*/
public function testDatabaseOperationFlags(): void
{
$context = $this->createContext([
'readerType' => '漂洗',
'currentStep' => '清洗',
]);
$this->node->handle($context);
$this->assertTrue($context->needDatabaseOperation);
$this->assertEquals(DbOperationType::INSERT, $context->dbOperation);
}
/**
* 测试 WebSocket 通知标记
*/
public function testWebSocketNotifyFlag(): void
{
$context = $this->createContext([
'readerType' => '漂洗',
'currentStep' => '清洗',
]);
$this->node->handle($context);
$this->assertTrue($context->needWebSocketNotify);
}
/**
* 测试节点被禁用后直接跳过
*/
public function testDisabledNodeSkips(): void
{
$this->node->setEnabled(false);
$context = $this->createContext([
'readerType' => '漂洗',
'currentStep' => '清洗',
]);
$result = $this->node->handle($context);
// 被禁用,currentStep 不应该变为漂洗
$this->assertEquals('清洗', $result->currentStep);
}
}
+148
View File
@@ -0,0 +1,148 @@
<?php
namespace tests\flow\nodes;
use tests\flow\TestCase;
use app\flow\nodes\WashNode;
use app\flow\DbOperationType;
/**
* 清洗节点单元测试
*/
class WashNodeTest extends TestCase
{
protected WashNode $node;
protected function setUp(): void
{
$this->node = new WashNode();
}
/**
* 测试节点名称和编码
*/
public function testNodeIdentity(): void
{
$this->assertEquals('清洗', $this->node->getName());
$this->assertEquals('清洗', $this->node->getCode());
}
/**
* 测试可以处理清洗读卡器
*/
public function testCanHandleWashReader(): void
{
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => '',
'morningWashed' => true,
]);
$this->assertTrue($this->node->canHandle($context));
}
/**
* 测试不能处理非清洗读卡器
*/
public function testCannotHandleNonWashReader(): void
{
$context = $this->createContext([
'readerType' => '消毒',
'currentStep' => '',
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试新流程可以开始清洗
*/
public function testCanStartNewWashProcess(): void
{
$validSteps = ['', '结束', '内镜取出', '内镜放入', '测漏正常'];
foreach ($validSteps as $step) {
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => $step,
'morningWashed' => true,
]);
$this->assertTrue(
$this->node->canHandle($context),
"步骤 '{$step}' 应该可以开始清洗"
);
}
}
/**
* 测试未完成晨洗不能开始清洗
*/
public function testCannotWashWithoutMorningWash(): void
{
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => '',
'needMorningWash' => true,
'morningWashed' => false,
]);
$this->assertFalse($this->node->canHandle($context));
}
/**
* 测试处理流程
*/
public function testHandleProcess(): void
{
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => '',
'morningWashed' => true,
'endoscopeId' => '', // 避免触发 DB 查询
]);
$result = $this->node->handle($context);
$this->assertSuccess($result);
$this->assertStep($result, '清洗');
$this->assertEquals('手工洗', $result->processType);
$this->assertNotNull($result->getStepLastTime('清洗'));
}
/**
* 测试生成批次号
*/
public function testGenerateBatchNo(): void
{
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => '',
'morningWashed' => true,
'endoscopeId' => '', // 避免触发 DB 查询
]);
$this->node->handle($context);
$this->assertNotEmpty($context->batchNo);
$this->assertTrue($context->needDatabaseOperation);
$this->assertEquals(DbOperationType::INSERT, $context->dbOperation);
}
/**
* 测试已有批次号不重新生成
*/
public function testKeepExistingBatchNo(): void
{
$context = $this->createContext([
'readerType' => '清洗',
'currentStep' => '漂洗', // 已有流程
'batchNo' => 'EXISTING001',
'morningWashed' => true,
]);
$this->node->handle($context);
$this->assertEquals('EXISTING001', $context->batchNo);
}
}