import { describe, it, expect, vi, beforeEach } from 'vitest';
import { createMockMySQLAdapter, createMockQueryResult, createMockRequestContext } from '../../../../__tests__/mocks/index.js';
import type { MySQLAdapter } from '../../MySQLAdapter.js';
import { createClusterResource } from '../cluster.js';
describe('Cluster Resource', () => {
let mockAdapter: ReturnType<typeof createMockMySQLAdapter>;
let mockContext: ReturnType<typeof createMockRequestContext>;
beforeEach(() => {
vi.clearAllMocks();
mockAdapter = createMockMySQLAdapter();
mockContext = createMockRequestContext();
});
it('should return cluster status when group replication is enabled', async () => {
// Mock group_replication_group_name
mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
{ Variable_name: 'group_replication_group_name', Value: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' }
]));
// Mock replication_group_members
mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
{ id: '1', host: 'host1', port: 3306, state: 'ONLINE', role: 'PRIMARY', version: '8.0.35' },
{ id: '2', host: 'host2', port: 3306, state: 'ONLINE', role: 'SECONDARY', version: '8.0.35' }
]));
// Mock primary member query
mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
{ host: 'host1', port: 3306 }
]));
const resource = createClusterResource(mockAdapter as unknown as MySQLAdapter);
const result = await resource.handler('mysql://cluster', mockContext) as any;
expect(result.groupReplicationEnabled).toBe(true);
expect(result.groupName).toBe('aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee');
expect(result.memberCount).toBe(2);
expect(result.primary).toBe('host1:3306');
});
it('should return disabled status if group name is empty', async () => {
// Mock group_replication_group_name with empty value
mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
{ Variable_name: 'group_replication_group_name', Value: '' }
]));
const resource = createClusterResource(mockAdapter as unknown as MySQLAdapter);
const result = await resource.handler('mysql://cluster', mockContext) as any;
expect(result.groupReplicationEnabled).toBe(false);
expect(result.message).toContain('not configured');
});
it('should return disabled status if variable query returns empty', async () => {
// Mock group_replication_group_name with no rows
mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
const resource = createClusterResource(mockAdapter as unknown as MySQLAdapter);
const result = await resource.handler('mysql://cluster', mockContext) as any;
expect(result.groupReplicationEnabled).toBe(false);
});
it('should handle undefined rows gracefully', async () => {
// Mock empty result with undefined rows
mockAdapter.executeQuery.mockResolvedValueOnce({} as any);
const resource = createClusterResource(mockAdapter as unknown as MySQLAdapter);
const result = await resource.handler('mysql://cluster', mockContext) as any;
expect(result.groupReplicationEnabled).toBe(false);
});
it('should handle missing primary member', async () => {
// Mock group_replication_group_name
mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
{ Variable_name: 'group_replication_group_name', Value: 'uuid' }
]));
// Mock members (no primary)
mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
{ id: '1', role: 'SECONDARY' }
]));
// Mock primary query (empty)
mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
const resource = createClusterResource(mockAdapter as unknown as MySQLAdapter);
const result = await resource.handler('mysql://cluster', mockContext) as any;
expect(result.groupReplicationEnabled).toBe(true);
expect(result.primary).toBeNull();
});
it('should handle errors gracefully', async () => {
mockAdapter.executeQuery.mockRejectedValue(new Error('DB Error'));
const resource = createClusterResource(mockAdapter as unknown as MySQLAdapter);
const result = await resource.handler('mysql://cluster', mockContext) as any;
expect(result.groupReplicationEnabled).toBe(false);
expect(result.message).toContain('Unable to retrieve');
});
});