Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 32 additions & 34 deletions tests/Feature/Mcp/Tools/ApplicationInfoTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Laravel\Boost\Install\GuidelineAssist;
use Laravel\Boost\Mcp\Tools\ApplicationInfo;
use Laravel\Mcp\Server\Tools\ToolResult;
use Laravel\Roster\Enums\Packages;
use Laravel\Roster\Package;
use Laravel\Roster\PackageCollection;
Expand All @@ -28,26 +27,29 @@
$tool = new ApplicationInfo($roster, $guidelineAssist);
$result = $tool->handle([]);

expect($result)->toBeInstanceOf(ToolResult::class);

$data = $result->toArray();
expect($data['isError'])->toBeFalse();

$content = json_decode($data['content'][0]['text'], true);
expect($content['php_version'])->toBe(PHP_VERSION);
expect($content['laravel_version'])->toBe(app()->version());
expect($content['database_engine'])->toBe(config('database.default'));
expect($content['packages'])->toHaveCount(2);
expect($content['packages'][0]['roster_name'])->toBe('LARAVEL');
expect($content['packages'][0]['package_name'])->toBe('laravel/framework');
expect($content['packages'][0]['version'])->toBe('11.0.0');
expect($content['packages'][1]['roster_name'])->toBe('PEST');
expect($content['packages'][1]['package_name'])->toBe('pestphp/pest');
expect($content['packages'][1]['version'])->toBe('2.0.0');
expect($content['models'])->toBeArray();
expect($content['models'])->toHaveCount(2);
expect($content['models'])->toContain('App\\Models\\User');
expect($content['models'])->toContain('App\\Models\\Post');
expect($result)->isToolResult()
->toolHasNoError()
->toolJsonContentToMatchArray([
'php_version' => PHP_VERSION,
'laravel_version' => app()->version(),
'database_engine' => config('database.default'),
'packages' => [
[
'roster_name' => 'LARAVEL',
'package_name' => 'laravel/framework',
'version' => '11.0.0',
],
[
'roster_name' => 'PEST',
'package_name' => 'pestphp/pest',
'version' => '2.0.0',
],
],
'models' => [
'App\\Models\\User',
'App\\Models\\Post',
],
]);
});

test('it returns application info with no packages', function () {
Expand All @@ -60,17 +62,13 @@
$tool = new ApplicationInfo($roster, $guidelineAssist);
$result = $tool->handle([]);

expect($result)->toBeInstanceOf(ToolResult::class);
expect($result)->toBeInstanceOf(ToolResult::class);

$data = $result->toArray();
expect($data['isError'])->toBeFalse();

$content = json_decode($data['content'][0]['text'], true);
expect($content['php_version'])->toBe(PHP_VERSION);
expect($content['laravel_version'])->toBe(app()->version());
expect($content['database_engine'])->toBe(config('database.default'));
expect($content['packages'])->toHaveCount(0);
expect($content['models'])->toBeArray();
expect($content['models'])->toHaveCount(0);
expect($result)->isToolResult()
->toolHasNoError()
->toolJsonContentToMatchArray([
'php_version' => PHP_VERSION,
'laravel_version' => app()->version(),
'database_engine' => config('database.default'),
'packages' => [],
'models' => [],
]);
});
69 changes: 29 additions & 40 deletions tests/Feature/Mcp/Tools/BrowserLogsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use Laravel\Boost\Mcp\Tools\BrowserLogs;
use Laravel\Boost\Middleware\InjectBoost;
use Laravel\Boost\Services\BrowserLogger;
use Laravel\Mcp\Server\Tools\ToolResult;

beforeEach(function () {
// Clean up any existing browser.log file before each test
Expand All @@ -36,47 +35,38 @@
$tool = new BrowserLogs;
$result = $tool->handle(['entries' => 2]);

expect($result)->toBeInstanceOf(ToolResult::class);
expect($result)->isToolResult()
->toolHasNoError()
->toolTextContains('browser.WARNING: Warning message', 'browser.ERROR: JavaScript error occurred')
->toolTextDoesNotContain('browser.DEBUG: console log message');

$data = $result->toArray();
expect($data['isError'])->toBeFalse();
expect($data['content'][0]['type'])->toBe('text');

$text = $data['content'][0]['text'];
expect($text)->toContain('browser.WARNING: Warning message');
expect($text)->toContain('browser.ERROR: JavaScript error occurred');
expect($text)->not->toContain('browser.DEBUG: console log message');
});

test('it returns error when entries argument is invalid', function () {
$tool = new BrowserLogs;

// Test with zero
$result = $tool->handle(['entries' => 0]);
expect($result)->toBeInstanceOf(ToolResult::class);

$data = $result->toArray();
expect($data['isError'])->toBeTrue();
expect($data['content'][0]['text'])->toBe('The "entries" argument must be greater than 0.');
expect($result)->isToolResult()
->toolHasError()
->toolTextContains('The "entries" argument must be greater than 0.');

// Test with negative
$result = $tool->handle(['entries' => -5]);
expect($result)->toBeInstanceOf(ToolResult::class);

$data = $result->toArray();
expect($data['isError'])->toBeTrue();
expect($data['content'][0]['text'])->toBe('The "entries" argument must be greater than 0.');
expect($result)->isToolResult()
->toolHasError()
->toolTextContains('The "entries" argument must be greater than 0.');
});

test('it returns error when log file does not exist', function () {
$tool = new BrowserLogs;
$result = $tool->handle(['entries' => 10]);

expect($result)->toBeInstanceOf(ToolResult::class);

$data = $result->toArray();
expect($data['isError'])->toBeTrue();
expect($data['content'][0]['text'])->toBe('No log file found, probably means no logs yet.');
expect($result)->isToolResult()
->toolHasError()
->toolTextContains('No log file found, probably means no logs yet.');
});

test('it returns error when log file is empty', function () {
Expand All @@ -88,11 +78,9 @@
$tool = new BrowserLogs;
$result = $tool->handle(['entries' => 5]);

expect($result)->toBeInstanceOf(ToolResult::class);

$data = $result->toArray();
expect($data['isError'])->toBeFalse();
expect($data['content'][0]['text'])->toBe('Unable to retrieve log entries, or no logs');
expect($result)->isToolResult()
->toolHasNoError()
->toolTextContains('Unable to retrieve log entries, or no logs');
});

test('@boostJs blade directive renders browser logger script', function () {
Expand All @@ -106,11 +94,11 @@

// Test that the script contains expected content
$script = BrowserLogger::getScript();
expect($script)->toContain('browser-logger-active');
expect($script)->toContain('/_boost/browser-logs');
expect($script)->toContain('console.log');
expect($script)->toContain('console.error');
expect($script)->toContain('window.onerror');
expect($script)->toContain('browser-logger-active')
->and($script)->toContain('/_boost/browser-logs')
->and($script)->toContain('console.log')
->and($script)->toContain('console.error')
->and($script)->toContain('window.onerror');
});

test('browser logs endpoint processes logs correctly', function () {
Expand Down Expand Up @@ -215,9 +203,10 @@
});

$content = $result->getContent();
expect($content)->toContain('browser-logger-active');
expect($content)->toContain('</head>');
expect(substr_count($content, 'browser-logger-active'))->toBe(1); // Should not inject twice
expect($content)->toContain('browser-logger-active')
->and($content)->toContain('</head>')
// Should not inject twice
->and(substr_count($content, 'browser-logger-active'))->toBe(1);
});

test('InjectBoost middleware does not inject into non-HTML responses', function () {
Expand All @@ -233,8 +222,8 @@
});

$content = $result->getContent();
expect($content)->toBe($json);
expect($content)->not->toContain('browser-logger-active');
expect($content)->toBe($json)
->and($content)->not->toContain('browser-logger-active');
});

test('InjectBoost middleware does not inject script twice', function () {
Expand Down Expand Up @@ -284,6 +273,6 @@
});

$content = $result->getContent();
expect($content)->toContain('browser-logger-active');
expect($content)->toMatch('/<script[^>]*browser-logger-active[^>]*>.*<\/script>\s*<\/body>/s');
expect($content)->toContain('browser-logger-active')
->and($content)->toMatch('/<script[^>]*browser-logger-active[^>]*>.*<\/script>\s*<\/body>/s');
});
30 changes: 12 additions & 18 deletions tests/Feature/Mcp/Tools/DatabaseConnectionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
declare(strict_types=1);

use Laravel\Boost\Mcp\Tools\DatabaseConnections;
use Laravel\Mcp\Server\Tools\ToolResult;

beforeEach(function () {
config()->set('database.default', 'mysql');
Expand All @@ -18,16 +17,12 @@
$tool = new DatabaseConnections;
$result = $tool->handle([]);

expect($result)->toBeInstanceOf(ToolResult::class);
$data = $result->toArray();
expect($data['isError'])->toBe(false);

$content = json_decode($data['content'][0]['text'], true);
expect($content['default_connection'])->toBe('mysql');
expect($content['connections'])->toHaveCount(3);
expect($content['connections'])->toContain('mysql');
expect($content['connections'])->toContain('pgsql');
expect($content['connections'])->toContain('sqlite');
expect($result)->isToolResult()
->toolHasNoError()
->toolJsonContentToMatchArray([
'default_connection' => 'mysql',
'connections' => ['mysql', 'pgsql', 'sqlite'],
]);
});

test('it returns empty connections when none configured', function () {
Expand All @@ -36,11 +31,10 @@
$tool = new DatabaseConnections;
$result = $tool->handle([]);

expect($result)->toBeInstanceOf(ToolResult::class);
$data = $result->toArray();
expect($data['isError'])->toBe(false);

$content = json_decode($data['content'][0]['text'], true);
expect($content['default_connection'])->toBe('mysql');
expect($content['connections'])->toHaveCount(0);
expect($result)->isToolResult()
->toolHasNoError()
->toolJsonContentToMatchArray([
'default_connection' => 'mysql',
'connections' => [],
]);
});
69 changes: 30 additions & 39 deletions tests/Feature/Mcp/Tools/DatabaseSchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,35 +39,24 @@
$tool = new DatabaseSchema;
$response = $tool->handle([]);

$responseArray = $response->toArray();
expect($responseArray['isError'])->toBeFalse();

$schemaArray = json_decode($responseArray['content'][0]['text'], true);

expect($schemaArray)->toHaveKey('engine');
expect($schemaArray['engine'])->toBe('sqlite');

expect($schemaArray)->toHaveKey('tables');
expect($schemaArray['tables'])->toHaveKey('examples');

$exampleTable = $schemaArray['tables']['examples'];
expect($exampleTable)->toHaveKey('columns');
expect($exampleTable['columns'])->toHaveKey('id');
expect($exampleTable['columns'])->toHaveKey('name');

expect($exampleTable['columns']['id']['type'])->toBe('integer');
expect($exampleTable['columns']['name']['type'])->toBe('varchar');

expect($exampleTable)->toHaveKey('indexes');
expect($exampleTable)->toHaveKey('foreign_keys');
expect($exampleTable)->toHaveKey('triggers');
expect($exampleTable)->toHaveKey('check_constraints');

expect($schemaArray)->toHaveKey('global');
expect($schemaArray['global'])->toHaveKey('views');
expect($schemaArray['global'])->toHaveKey('stored_procedures');
expect($schemaArray['global'])->toHaveKey('functions');
expect($schemaArray['global'])->toHaveKey('sequences');
expect($response)->isToolResult()
->toolHasNoError()
->toolJsonContentToMatchArray([
'engine' => 'sqlite',
])
->toolJsonContent(function ($schemaArray) {
expect($schemaArray)->toHaveKey('tables')
->and($schemaArray['tables'])->toHaveKey('examples');

$exampleTable = $schemaArray['tables']['examples'];
expect($exampleTable)->toHaveKeys(['columns', 'indexes', 'foreign_keys', 'triggers', 'check_constraints'])
->and($exampleTable['columns'])->toHaveKeys(['id', 'name'])
->and($exampleTable['columns']['id']['type'])->toBe('integer')
->and($exampleTable['columns']['name']['type'])->toBe('varchar')
->and($schemaArray)->toHaveKey('global')
->and($schemaArray['global'])->toHaveKeys(['views', 'stored_procedures', 'functions', 'sequences']);

});
});

test('it filters tables by name', function () {
Expand All @@ -81,17 +70,19 @@

// Test filtering for 'example'
$response = $tool->handle(['filter' => 'example']);
$responseArray = $response->toArray();
$schemaArray = json_decode($responseArray['content'][0]['text'], true);

expect($schemaArray['tables'])->toHaveKey('examples');
expect($schemaArray['tables'])->not->toHaveKey('users');
expect($response)->isToolResult()
->toolHasNoError()
->toolJsonContent(function ($schemaArray) {
expect($schemaArray['tables'])->toHaveKey('examples')
->and($schemaArray['tables'])->not->toHaveKey('users');
});

// Test filtering for 'user'
$response = $tool->handle(['filter' => 'user']);
$responseArray = $response->toArray();
$schemaArray = json_decode($responseArray['content'][0]['text'], true);

expect($schemaArray['tables'])->toHaveKey('users');
expect($schemaArray['tables'])->not->toHaveKey('examples');
expect($response)->isToolResult()
->toolHasNoError()
->toolJsonContent(function ($schemaArray) {
expect($schemaArray['tables'])->toHaveKey('users')
->and($schemaArray['tables'])->not->toHaveKey('examples');
});
});
Loading