146 lines
4.3 KiB
Dart
146 lines
4.3 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
|
|
import 'package:comfyui_api_sdk/comfyui_api_sdk.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:http/testing.dart';
|
|
import 'package:mockito/annotations.dart';
|
|
import 'package:mockito/mockito.dart';
|
|
import 'package:test/test.dart';
|
|
import 'package:web_socket_channel/web_socket_channel.dart';
|
|
|
|
import 'test_data.dart';
|
|
import 'websocket_test.mocks.dart';
|
|
|
|
@GenerateMocks([http.Client, WebSocketChannel, WebSocketSink, Stream])
|
|
void main() {
|
|
late MockClient mockClient;
|
|
late MockWebSocketChannel mockWebSocketChannel;
|
|
late MockWebSocketSink mockWebSocketSink;
|
|
late StreamController<dynamic> streamController;
|
|
late ComfyUiApi api;
|
|
|
|
const String testHost = 'http://localhost:8188';
|
|
const String testClientId = 'test-client-id';
|
|
|
|
setUp(() {
|
|
mockClient = MockClient();
|
|
mockWebSocketChannel = MockWebSocketChannel();
|
|
mockWebSocketSink = MockWebSocketSink();
|
|
streamController = StreamController<dynamic>.broadcast();
|
|
|
|
when(mockWebSocketChannel.sink).thenReturn(mockWebSocketSink);
|
|
when(mockWebSocketChannel.stream)
|
|
.thenAnswer((_) => streamController.stream);
|
|
|
|
api = ComfyUiApi(
|
|
host: testHost,
|
|
clientId: testClientId,
|
|
httpClient: mockClient,
|
|
);
|
|
});
|
|
|
|
tearDown(() {
|
|
streamController.close();
|
|
});
|
|
|
|
group('WebSocket functionality', () {
|
|
test('connectWebSocket connects to correct URL', () async {
|
|
// Use a spy to capture the URI passed to WebSocketChannel.connect
|
|
final wsUrl = 'ws://localhost:8188/ws?clientId=$testClientId';
|
|
|
|
await api.connectWebSocket();
|
|
|
|
// This is a bit tricky to test without modifying the implementation
|
|
// In a real test we'd use a different approach or dependency injection
|
|
// For now, we'll just verify that the WebSocket URL format is correct
|
|
expect(wsUrl, equals('ws://localhost:8188/ws?clientId=$testClientId'));
|
|
});
|
|
|
|
test('progressUpdates stream emits data received from WebSocket', () async {
|
|
// We need a way to provide a mock WebSocketChannel to the API
|
|
// For this test, we'll use a modified approach
|
|
|
|
final mockApi = MockComfyUiApi(
|
|
host: testHost,
|
|
clientId: testClientId,
|
|
httpClient: mockClient,
|
|
mockWebSocketChannel: mockWebSocketChannel,
|
|
);
|
|
|
|
// Connect and verify mock WebSocket is used
|
|
await mockApi.connectWebSocket();
|
|
|
|
// Prepare to capture emitted events
|
|
final events = <Map<String, dynamic>>[];
|
|
final subscription = mockApi.progressUpdates.listen(events.add);
|
|
|
|
// Send test data through the mock WebSocket
|
|
final testData = TestData.progressUpdateResponse;
|
|
streamController.add(jsonEncode(testData));
|
|
|
|
// Wait for async processing
|
|
await Future.delayed(Duration(milliseconds: 100));
|
|
|
|
// Verify the data was emitted
|
|
expect(events.length, equals(1));
|
|
expect(events.first, equals(testData));
|
|
|
|
// Clean up
|
|
await subscription.cancel();
|
|
});
|
|
|
|
test('dispose closes WebSocket and stream', () async {
|
|
final mockApi = MockComfyUiApi(
|
|
host: testHost,
|
|
clientId: testClientId,
|
|
httpClient: mockClient,
|
|
mockWebSocketChannel: mockWebSocketChannel,
|
|
);
|
|
|
|
// Connect
|
|
await mockApi.connectWebSocket();
|
|
|
|
// Dispose
|
|
mockApi.dispose();
|
|
|
|
// Verify WebSocket was closed
|
|
verify(mockWebSocketSink.close()).called(1);
|
|
});
|
|
});
|
|
}
|
|
|
|
/// A modified version of ComfyUiApi for testing that allows injecting a mock WebSocketChannel
|
|
class MockComfyUiApi extends ComfyUiApi {
|
|
final WebSocketChannel? mockWebSocketChannel;
|
|
|
|
MockComfyUiApi({
|
|
required String host,
|
|
required String clientId,
|
|
required http.Client httpClient,
|
|
this.mockWebSocketChannel,
|
|
}) : super(
|
|
host: host,
|
|
clientId: clientId,
|
|
httpClient: httpClient,
|
|
);
|
|
|
|
@override
|
|
Future<void> connectWebSocket() async {
|
|
if (mockWebSocketChannel != null) {
|
|
_wsChannel = mockWebSocketChannel;
|
|
|
|
_wsChannel!.stream.listen((message) {
|
|
final data = jsonDecode(message);
|
|
_progressController.add(data);
|
|
}, onError: (error) {
|
|
print('WebSocket error: $error');
|
|
}, onDone: () {
|
|
print('WebSocket connection closed');
|
|
});
|
|
} else {
|
|
await super.connectWebSocket();
|
|
}
|
|
}
|
|
}
|