Files
michaelschiemer/tests/Feature/GraphQLSubscriptionsTest.php
Michael Schiemer 5050c7d73a docs: consolidate documentation into organized structure
- Move 12 markdown files from root to docs/ subdirectories
- Organize documentation by category:
  • docs/troubleshooting/ (1 file)  - Technical troubleshooting guides
  • docs/deployment/      (4 files) - Deployment and security documentation
  • docs/guides/          (3 files) - Feature-specific guides
  • docs/planning/        (4 files) - Planning and improvement proposals

Root directory cleanup:
- Reduced from 16 to 4 markdown files in root
- Only essential project files remain:
  • CLAUDE.md (AI instructions)
  • README.md (Main project readme)
  • CLEANUP_PLAN.md (Current cleanup plan)
  • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements)

This improves:
 Documentation discoverability
 Logical organization by purpose
 Clean root directory
 Better maintainability
2025-10-05 11:05:04 +02:00

158 lines
5.6 KiB
PHP

<?php
use App\Application\GraphQL\NotificationPublisher;
use App\Application\GraphQL\NotificationSubscriptions;
use App\Framework\GraphQL\Attributes\GraphQLSubscription;
use App\Framework\GraphQL\Execution\QueryParser;
use App\Framework\GraphQL\Schema\SchemaBuilder;
use App\Framework\GraphQL\Subscriptions\SubscriptionId;
use App\Framework\GraphQL\Subscriptions\SubscriptionManager;
use App\Framework\GraphQL\Subscriptions\SubscriptionRegistry;
use App\Framework\Http\WebSocketConnectionInterface;
describe('GraphQL Subscriptions', function () {
beforeEach(function () {
$this->registry = new SubscriptionRegistry();
// Create mock WebSocket connection using Mockery
$this->connection = Mockery::mock(WebSocketConnectionInterface::class);
$this->connection->shouldReceive('getId')->andReturn('test-connection-1');
$this->connection->shouldReceive('isConnected')->andReturn(true);
$this->connection->shouldReceive('sendJson')->andReturnTrue();
$this->connection->shouldReceive('setAttribute')->andReturnNull();
$this->connection->shouldReceive('getAttribute')->andReturn(null);
$this->sentMessages = [];
});
it('can register and retrieve subscriptions', function () {
$id = SubscriptionId::generate();
$this->registry->register(
$id,
$this->connection,
'notificationReceived',
['userId' => '123']
);
$subscriptions = $this->registry->getByName('notificationReceived');
expect($subscriptions)->toHaveCount(1);
expect($subscriptions[0]['id']->toString())->toBe($id->toString());
expect($subscriptions[0]['variables']['userId'])->toBe('123');
});
it('can unregister subscriptions', function () {
$id = SubscriptionId::generate();
$this->registry->register(
$id,
$this->connection,
'notificationReceived',
['userId' => '123']
);
expect($this->registry->getByName('notificationReceived'))->toHaveCount(1);
$this->registry->unregister($id);
expect($this->registry->getByName('notificationReceived'))->toHaveCount(0);
});
it('can cleanup subscriptions by connection', function () {
$id1 = SubscriptionId::generate();
$id2 = SubscriptionId::generate();
$this->registry->register(
$id1,
$this->connection,
'notificationReceived',
['userId' => '123']
);
$this->registry->register(
$id2,
$this->connection,
'orderStatusChanged',
['orderId' => 'order-1']
);
expect($this->registry->getByName('notificationReceived'))->toHaveCount(1);
expect($this->registry->getByName('orderStatusChanged'))->toHaveCount(1);
$this->registry->removeByConnection($this->connection);
expect($this->registry->getByName('notificationReceived'))->toHaveCount(0);
expect($this->registry->getByName('orderStatusChanged'))->toHaveCount(0);
});
it('provides subscription statistics', function () {
$this->registry->register(
SubscriptionId::generate(),
$this->connection,
'notificationReceived',
['userId' => '123']
);
$this->registry->register(
SubscriptionId::generate(),
$this->connection,
'orderStatusChanged',
['orderId' => 'order-1']
);
$stats = $this->registry->getStats();
expect($stats['total_subscriptions'])->toBe(2);
expect($stats['unique_connections'])->toBe(1);
expect($stats['subscriptions_by_type']['notificationReceived'])->toBe(1);
expect($stats['subscriptions_by_type']['orderStatusChanged'])->toBe(1);
});
it('discovers GraphQLSubscription classes', function () {
$reflection = new ReflectionClass(NotificationSubscriptions::class);
$attribute = $reflection->getAttributes(GraphQLSubscription::class)[0] ?? null;
expect($attribute)->not->toBeNull();
$instance = $attribute->newInstance();
expect($instance->description)->toBe('Real-time notification subscriptions');
});
it('builds subscription fields in schema', function () {
// Create simple container for testing
$container = new \App\Framework\DI\DefaultContainer();
$typeResolver = new \App\Framework\GraphQL\Schema\TypeResolver();
$schemaBuilder = new SchemaBuilder($container, $typeResolver);
$schema = $schemaBuilder->build([
NotificationSubscriptions::class,
]);
expect($schema->subscriptions)->toHaveCount(3);
expect($schema->getSubscription('notificationReceived'))->not->toBeNull();
expect($schema->getSubscription('orderStatusChanged'))->not->toBeNull();
expect($schema->getSubscription('systemAnnouncement'))->not->toBeNull();
});
it('generates correct SDL for subscriptions', function () {
// Create simple container for testing
$container = new \App\Framework\DI\DefaultContainer();
$typeResolver = new \App\Framework\GraphQL\Schema\TypeResolver();
$schemaBuilder = new SchemaBuilder($container, $typeResolver);
$schema = $schemaBuilder->build([
NotificationSubscriptions::class,
]);
$sdl = $schema->toSDL();
expect($sdl)->toContain('type Subscription {');
expect($sdl)->toContain('notificationReceived');
expect($sdl)->toContain('orderStatusChanged');
expect($sdl)->toContain('systemAnnouncement');
});
});