diff --git a/php/tests/Feature/Mcp/BrainSmokeTest.php b/php/tests/Feature/Mcp/BrainSmokeTest.php new file mode 100644 index 0000000..6385d7f --- /dev/null +++ b/php/tests/Feature/Mcp/BrainSmokeTest.php @@ -0,0 +1,144 @@ +forgetCalled = true; + + DB::connection('brain')->transaction(function () use ($id): void { + BrainMemory::where('id', $id)->delete(); + }); + } + }; +} + +/** + * @return array{workspace: \Core\Tenant\Models\Workspace, session: AgentSession, context: array{workspace_id: int, session_id: string}} + */ +function brainSmokeContext(): array +{ + $workspace = createWorkspace(); + $session = AgentSession::start(null, AgentSession::AGENT_OPUS, $workspace); + + return [ + 'workspace' => $workspace, + 'session' => $session, + 'context' => [ + 'workspace_id' => $workspace->id, + 'session_id' => $session->session_id, + ], + ]; +} + +test('BrainSmoke_remember_list_forget_Good_exercises_mariadb_only_handlers_end_to_end', function (): void { + Queue::fake(); + + $brain = brainSmokeService(); + $this->app->instance(BrainService::class, $brain); + + [ + 'workspace' => $workspace, + 'session' => $session, + 'context' => $context, + ] = brainSmokeContext(); + + $rememberPayload = [ + 'content' => 'test memory about X', + 'scope' => 'workspace', + 'type' => 'context', + 'tags' => ['smoketest'], + ]; + + $rememberResult = (new BrainRemember)->handle($rememberPayload, $context); + + expect($rememberResult)->toBeArray() + ->and($rememberResult['success'])->toBeTrue() + ->and($rememberResult['memory']['id'])->toBeString() + ->and($rememberResult['memory']['content'])->toBe($rememberPayload['content']) + ->and($rememberResult['memory']['type'])->toBe($rememberPayload['type']) + ->and($rememberResult['memory']['tags'])->toBe($rememberPayload['tags']) + ->and($rememberResult['memory']['agent_id'])->toBe($session->session_id); + + $memoryId = $rememberResult['memory']['id']; + $storedMemory = BrainMemory::query()->find($memoryId); + + expect($storedMemory)->not->toBeNull() + ->and($storedMemory?->workspace_id)->toBe($workspace->id) + ->and($storedMemory?->content)->toBe($rememberPayload['content']) + ->and($storedMemory?->type)->toBe($rememberPayload['type']) + ->and($storedMemory?->tags)->toBe($rememberPayload['tags']) + ->and($storedMemory?->deleted_at)->toBeNull(); + + Queue::assertPushed(EmbedMemory::class, fn (EmbedMemory $job): bool => $job->memoryId === $memoryId); + + $listResult = (new BrainList)->handle([ + 'scope' => 'workspace', + ], $context); + + expect($listResult)->toBeArray() + ->and($listResult['success'])->toBeTrue() + ->and($listResult['count'])->toBe(1) + ->and($listResult['memories'])->toHaveCount(1) + ->and($listResult['memories'][0]['id'])->toBe($memoryId) + ->and($listResult['memories'][0]['agent_id'])->toBe($session->session_id) + ->and($listResult['memories'][0]['content'])->toBe($rememberPayload['content']) + ->and($listResult['memories'][0]['type'])->toBe($rememberPayload['type']) + ->and($listResult['memories'][0]['tags'])->toBe($rememberPayload['tags']); + + $forgetResult = (new BrainForget)->handle([ + 'id' => $memoryId, + ], $context); + + expect($forgetResult)->toBeArray() + ->and($forgetResult['success'])->toBeTrue() + ->and($forgetResult['forgotten'])->toBe($memoryId) + ->and($forgetResult['type'])->toBe($rememberPayload['type']) + ->and($brain->forgetCalled)->toBeTrue(); + + $deletedMemory = BrainMemory::withTrashed()->find($memoryId); + + expect(BrainMemory::query()->find($memoryId))->toBeNull() + ->and($deletedMemory)->not->toBeNull() + ->and($deletedMemory?->trashed())->toBeTrue(); +}); + +test('BrainSmoke_forget_Bad_reports_missing_memory_without_a_type_error', function (): void { + $brain = brainSmokeService(); + $this->app->instance(BrainService::class, $brain); + + ['context' => $context] = brainSmokeContext(); + + $missingId = '00000000-0000-4000-8000-000000000096'; + $tool = new BrainForget; + $result = null; + $reportedError = null; + + try { + $result = $tool->handle(['id' => $missingId], $context); + } catch (\InvalidArgumentException $exception) { + $reportedError = $exception->getMessage(); + } + + expect($reportedError ?? $result['error'] ?? null)->toBe("Memory '{$missingId}' not found in this workspace") + ->and($result['success'] ?? false)->toBeFalse() + ->and($brain->forgetCalled)->toBeFalse(); +});