forked from eatvio/eatvio_app
feat(video_calls): first impl for main video calls screen
This commit is contained in:
115
test/features/video_calls/models/video_call_models_test.dart
Normal file
115
test/features/video_calls/models/video_call_models_test.dart
Normal file
@@ -0,0 +1,115 @@
|
||||
import 'package:eatvio_app/features/video_calls/models/video_call_models.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../fixtures/fixture_reader.dart';
|
||||
|
||||
void main() {
|
||||
group('VideoCallTokenResponse', () {
|
||||
test('создаёт модель с правильными значениями', () {
|
||||
const model = VideoCallTokenResponse(
|
||||
token: 'ey-participant-token',
|
||||
roomName: 'conv-uuid-123',
|
||||
wsUrl: 'wss://livekit.eatvio.test/conv-uuid-123',
|
||||
);
|
||||
|
||||
expect(model.token, 'ey-participant-token');
|
||||
expect(model.roomName, 'conv-uuid-123');
|
||||
expect(model.wsUrl, 'wss://livekit.eatvio.test/conv-uuid-123');
|
||||
});
|
||||
|
||||
test('fromJson корректно десериализует ответ бэкенда', () {
|
||||
final json = FixtureReader.readAsMap('video_calls/video_call_token_response.json');
|
||||
|
||||
final model = VideoCallTokenResponse.fromJson(json);
|
||||
|
||||
expect(model.token, 'ey-participant-token');
|
||||
expect(model.roomName, 'conv-uuid-123');
|
||||
expect(model.wsUrl, 'wss://livekit.eatvio.test/conv-uuid-123');
|
||||
});
|
||||
|
||||
test('toJson сериализует модель в исходный JSON', () {
|
||||
final json = FixtureReader.readAsMap('video_calls/video_call_token_response.json');
|
||||
final model = VideoCallTokenResponse.fromJson(json);
|
||||
|
||||
final result = model.toJson();
|
||||
|
||||
expect(result['token'], 'ey-participant-token');
|
||||
expect(result['roomName'], 'conv-uuid-123');
|
||||
expect(result['wsUrl'], 'wss://livekit.eatvio.test/conv-uuid-123');
|
||||
});
|
||||
|
||||
test('round-trip JSON сохраняет значения', () {
|
||||
final json = FixtureReader.readAsMap('video_calls/video_call_token_response.json');
|
||||
|
||||
final model = VideoCallTokenResponse.fromJson(json);
|
||||
final restored = VideoCallTokenResponse.fromJson(model.toJson());
|
||||
|
||||
expect(restored, model);
|
||||
});
|
||||
});
|
||||
|
||||
group('VideoCallAdminTokenResponse', () {
|
||||
test('создаёт модель с правильными значениями', () {
|
||||
const model = VideoCallAdminTokenResponse(
|
||||
adminToken: 'ey-admin-token',
|
||||
roomName: 'conv-uuid-123',
|
||||
apiUrl: 'https://livekit.eatvio.test',
|
||||
);
|
||||
|
||||
expect(model.adminToken, 'ey-admin-token');
|
||||
expect(model.roomName, 'conv-uuid-123');
|
||||
expect(model.apiUrl, 'https://livekit.eatvio.test');
|
||||
});
|
||||
|
||||
test('fromJson корректно десериализует ответ бэкенда', () {
|
||||
final json = FixtureReader.readAsMap('video_calls/video_call_admin_token_response.json');
|
||||
|
||||
final model = VideoCallAdminTokenResponse.fromJson(json);
|
||||
|
||||
expect(model.adminToken, 'ey-admin-token');
|
||||
expect(model.roomName, 'conv-uuid-123');
|
||||
expect(model.apiUrl, 'https://livekit.eatvio.test');
|
||||
});
|
||||
|
||||
test('round-trip JSON сохраняет значения', () {
|
||||
final json = FixtureReader.readAsMap('video_calls/video_call_admin_token_response.json');
|
||||
|
||||
final model = VideoCallAdminTokenResponse.fromJson(json);
|
||||
final restored = VideoCallAdminTokenResponse.fromJson(model.toJson());
|
||||
|
||||
expect(restored, model);
|
||||
});
|
||||
});
|
||||
|
||||
group('VideoCallEndedResponse', () {
|
||||
test('fromJson десериализует sent=true', () {
|
||||
final json = FixtureReader.readAsMap('video_calls/video_call_ended_response.json');
|
||||
|
||||
final model = VideoCallEndedResponse.fromJson(json);
|
||||
|
||||
expect(model.sent, isTrue);
|
||||
});
|
||||
|
||||
test('fromJson десериализует sent=false', () {
|
||||
final model = VideoCallEndedResponse.fromJson(const {'sent': false});
|
||||
|
||||
expect(model.sent, isFalse);
|
||||
});
|
||||
|
||||
test('toJson сериализует модель', () {
|
||||
const model = VideoCallEndedResponse(sent: true);
|
||||
|
||||
final json = model.toJson();
|
||||
|
||||
expect(json['sent'], isTrue);
|
||||
});
|
||||
|
||||
test('round-trip JSON сохраняет значения', () {
|
||||
const model = VideoCallEndedResponse(sent: true);
|
||||
|
||||
final restored = VideoCallEndedResponse.fromJson(model.toJson());
|
||||
|
||||
expect(restored, model);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import 'package:eatvio_app/features/video_calls/models/video_call_models.dart';
|
||||
import 'package:eatvio_app/features/video_calls/repositories/video_call_repository.dart';
|
||||
import 'package:eatvio_app/features/video_calls/services/video_call_service.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import '../../../fixtures/fixture_reader.dart';
|
||||
import 'video_call_repository_test.mocks.dart';
|
||||
|
||||
@GenerateNiceMocks([MockSpec<VideoCallService>()])
|
||||
void main() {
|
||||
group('VideoCallRepository', () {
|
||||
late VideoCallRepository repository;
|
||||
late MockVideoCallService mockService;
|
||||
|
||||
setUp(() {
|
||||
mockService = MockVideoCallService();
|
||||
repository = VideoCallRepository(videoCallService: mockService);
|
||||
});
|
||||
|
||||
test('getParticipantToken - делегирует вызов сервису и возвращает токен', () async {
|
||||
const conversationUuid = 'conv-uuid-123';
|
||||
final json = FixtureReader.readAsMap('video_calls/video_call_token_response.json');
|
||||
final expected = VideoCallTokenResponse.fromJson(json);
|
||||
|
||||
when(mockService.getParticipantToken(conversationUuid: conversationUuid))
|
||||
.thenAnswer((_) async => expected);
|
||||
|
||||
final result = await repository.getParticipantToken(conversationUuid);
|
||||
|
||||
expect(result, isA<VideoCallTokenResponse>());
|
||||
expect(result.token, expected.token);
|
||||
expect(result.wsUrl, expected.wsUrl);
|
||||
expect(result.roomName, expected.roomName);
|
||||
verify(mockService.getParticipantToken(conversationUuid: conversationUuid)).called(1);
|
||||
});
|
||||
|
||||
test('getParticipantToken - пробрасывает ошибку сервиса', () async {
|
||||
const conversationUuid = 'conv-uuid-broken';
|
||||
|
||||
when(mockService.getParticipantToken(conversationUuid: conversationUuid))
|
||||
.thenThrow(Exception('No token'));
|
||||
|
||||
expect(
|
||||
() => repository.getParticipantToken(conversationUuid),
|
||||
throwsA(isA<Exception>()),
|
||||
);
|
||||
verify(mockService.getParticipantToken(conversationUuid: conversationUuid)).called(1);
|
||||
});
|
||||
|
||||
test('getAdminToken - делегирует вызов сервису и возвращает админский токен', () async {
|
||||
const conversationUuid = 'conv-uuid-123';
|
||||
final json = FixtureReader.readAsMap('video_calls/video_call_admin_token_response.json');
|
||||
final expected = VideoCallAdminTokenResponse.fromJson(json);
|
||||
|
||||
when(mockService.getAdminToken(conversationUuid: conversationUuid))
|
||||
.thenAnswer((_) async => expected);
|
||||
|
||||
final result = await repository.getAdminToken(conversationUuid);
|
||||
|
||||
expect(result, isA<VideoCallAdminTokenResponse>());
|
||||
expect(result.adminToken, expected.adminToken);
|
||||
expect(result.apiUrl, expected.apiUrl);
|
||||
verify(mockService.getAdminToken(conversationUuid: conversationUuid)).called(1);
|
||||
});
|
||||
|
||||
test('notifyCallEnded - вызывает сервис с пустым JSON-телом', () async {
|
||||
const conversationUuid = 'conv-uuid-123';
|
||||
final json = FixtureReader.readAsMap('video_calls/video_call_ended_response.json');
|
||||
final expected = VideoCallEndedResponse.fromJson(json);
|
||||
|
||||
when(mockService.notifyCallEnded(
|
||||
conversationUuid: conversationUuid,
|
||||
body: anyNamed('body'),
|
||||
)).thenAnswer((_) async => expected);
|
||||
|
||||
final result = await repository.notifyCallEnded(conversationUuid);
|
||||
|
||||
expect(result, isA<VideoCallEndedResponse>());
|
||||
expect(result.sent, isTrue);
|
||||
|
||||
final captured = verify(
|
||||
mockService.notifyCallEnded(
|
||||
conversationUuid: conversationUuid,
|
||||
body: captureAnyNamed('body'),
|
||||
),
|
||||
).captured;
|
||||
expect(captured, hasLength(1));
|
||||
expect(captured.single, isA<Map<String, dynamic>>());
|
||||
expect(captured.single as Map<String, dynamic>, isEmpty);
|
||||
});
|
||||
|
||||
test('notifyCallEnded - пробрасывает ошибку сервиса', () async {
|
||||
const conversationUuid = 'conv-uuid-broken';
|
||||
|
||||
when(mockService.notifyCallEnded(
|
||||
conversationUuid: conversationUuid,
|
||||
body: anyNamed('body'),
|
||||
)).thenThrow(Exception('Backend error'));
|
||||
|
||||
expect(
|
||||
() => repository.notifyCallEnded(conversationUuid),
|
||||
throwsA(isA<Exception>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import 'package:eatvio_app/features/video_calls/models/video_call_models.dart';
|
||||
import 'package:eatvio_app/features/video_calls/services/video_call_service.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import '../../../fixtures/fixture_reader.dart';
|
||||
import 'video_call_service_test.mocks.dart';
|
||||
|
||||
@GenerateNiceMocks([MockSpec<VideoCallService>()])
|
||||
void main() {
|
||||
group('VideoCallService', () {
|
||||
late MockVideoCallService mockService;
|
||||
|
||||
setUp(() {
|
||||
mockService = MockVideoCallService();
|
||||
});
|
||||
|
||||
test('getParticipantToken - возвращает токен и WebSocket URL', () async {
|
||||
const conversationUuid = 'conv-uuid-123';
|
||||
final json = FixtureReader.readAsMap('video_calls/video_call_token_response.json');
|
||||
final expected = VideoCallTokenResponse.fromJson(json);
|
||||
|
||||
when(mockService.getParticipantToken(conversationUuid: conversationUuid))
|
||||
.thenAnswer((_) async => expected);
|
||||
|
||||
final result = await mockService.getParticipantToken(conversationUuid: conversationUuid);
|
||||
|
||||
expect(result, isA<VideoCallTokenResponse>());
|
||||
expect(result.token, expected.token);
|
||||
expect(result.wsUrl, expected.wsUrl);
|
||||
expect(result.roomName, expected.roomName);
|
||||
verify(mockService.getParticipantToken(conversationUuid: conversationUuid)).called(1);
|
||||
});
|
||||
|
||||
test('getParticipantToken - пробрасывает ошибку', () async {
|
||||
const conversationUuid = 'conv-uuid-error';
|
||||
|
||||
when(mockService.getParticipantToken(conversationUuid: conversationUuid))
|
||||
.thenThrow(Exception('Network error'));
|
||||
|
||||
expect(
|
||||
() => mockService.getParticipantToken(conversationUuid: conversationUuid),
|
||||
throwsA(isA<Exception>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('getAdminToken - возвращает админский токен и API URL', () async {
|
||||
const conversationUuid = 'conv-uuid-123';
|
||||
final json = FixtureReader.readAsMap('video_calls/video_call_admin_token_response.json');
|
||||
final expected = VideoCallAdminTokenResponse.fromJson(json);
|
||||
|
||||
when(mockService.getAdminToken(conversationUuid: conversationUuid))
|
||||
.thenAnswer((_) async => expected);
|
||||
|
||||
final result = await mockService.getAdminToken(conversationUuid: conversationUuid);
|
||||
|
||||
expect(result, isA<VideoCallAdminTokenResponse>());
|
||||
expect(result.adminToken, expected.adminToken);
|
||||
expect(result.apiUrl, expected.apiUrl);
|
||||
expect(result.roomName, expected.roomName);
|
||||
verify(mockService.getAdminToken(conversationUuid: conversationUuid)).called(1);
|
||||
});
|
||||
|
||||
test('notifyCallEnded - отправляет пустое тело и получает sent=true', () async {
|
||||
const conversationUuid = 'conv-uuid-123';
|
||||
const body = <String, dynamic>{};
|
||||
final json = FixtureReader.readAsMap('video_calls/video_call_ended_response.json');
|
||||
final expected = VideoCallEndedResponse.fromJson(json);
|
||||
|
||||
when(mockService.notifyCallEnded(conversationUuid: conversationUuid, body: body))
|
||||
.thenAnswer((_) async => expected);
|
||||
|
||||
final result = await mockService.notifyCallEnded(conversationUuid: conversationUuid, body: body);
|
||||
|
||||
expect(result, isA<VideoCallEndedResponse>());
|
||||
expect(result.sent, isTrue);
|
||||
verify(mockService.notifyCallEnded(conversationUuid: conversationUuid, body: body)).called(1);
|
||||
});
|
||||
|
||||
test('notifyCallEnded - пробрасывает ошибку', () async {
|
||||
const conversationUuid = 'conv-uuid-error';
|
||||
const body = <String, dynamic>{};
|
||||
|
||||
when(mockService.notifyCallEnded(conversationUuid: conversationUuid, body: body))
|
||||
.thenThrow(Exception('Backend error'));
|
||||
|
||||
expect(
|
||||
() => mockService.notifyCallEnded(conversationUuid: conversationUuid, body: body),
|
||||
throwsA(isA<Exception>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import 'package:eatvio_app/features/video_calls/presentation/widgets/video_call_livekit_track_utils.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('VideoCallLiveKitTrackUtils', () {
|
||||
test('asVideoTrack возвращает null для null-трека', () {
|
||||
expect(VideoCallLiveKitTrackUtils.asVideoTrack(null), isNull);
|
||||
});
|
||||
|
||||
test('visibleVideoFromPublication возвращает null для null-публикации', () {
|
||||
expect(VideoCallLiveKitTrackUtils.visibleVideoFromPublication(null), isNull);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user