Files
ShowenV2/clients/flutter/test/models/models_test.dart
showen d30c111c71 feat: M1.1 完成 + M1.2 启动 — 全量更新
M1.1 收尾:
- 24项 P0/P1/P2 bug 修复 (Rust 107 tests + Flutter 15 tests)
- Flutter App v0.3: cupertino_icons 修复, 单元测试, 调试面板, APK 52.6MB
- 示例插件完善: manifest.json + 请求/响应示范 + 7个测试
- API 文档重写 (以 routes.rs 为唯一权威)
- MILESTONES.md 更新至 100%

M1.2 启动:
- P0: 插件管理 API 闭环 (handle_manager_message Custom 分支 + broadcast_plugin_states)
- ServiceManager 集成测试 8/8 (tests/m1_2_service_manager.rs)
- M1.2 测试计划 (docs/M1.2_TEST_PLAN.md, 18个E2E场景)
- 动态插件系统: auto_rollback + version_manager GC + 路径穿越防护

总计: Rust 115/115 测试, Flutter 15/15 测试, 零 warning

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 18:12:42 +08:00

184 lines
5.5 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:showen_v2_flutter/models/api_response.dart';
import 'package:showen_v2_flutter/models/app_event.dart';
import 'package:showen_v2_flutter/models/ble_models.dart';
import 'package:showen_v2_flutter/models/ble_status.dart';
import 'package:showen_v2_flutter/models/device_status.dart';
import 'package:showen_v2_flutter/models/player_status.dart';
import 'package:showen_v2_flutter/models/video_item.dart';
import 'package:showen_v2_flutter/models/wifi_network.dart';
import 'package:showen_v2_flutter/models/wifi_status.dart';
void main() {
group('ApiResponse', () {
test('fromJson and toJson round trip', () {
final response = ApiResponse.fromJson(const <String, dynamic>{
'status': 'ok',
'message': 'done',
});
expect(response.isOk, isTrue);
expect(response.toJson(), <String, dynamic>{
'status': 'ok',
'message': 'done',
});
});
});
group('AppEvent', () {
test('fromJson prefers data payload map', () {
final event = AppEvent.fromJson(const <String, dynamic>{
'type': 'status',
'data': <String, dynamic>{'connected': true},
});
expect(event.type, 'status');
expect(event.payload, <String, dynamic>{'connected': true});
});
test('fromJson normalizes scalar payload', () {
final event = AppEvent.fromJson(const <String, dynamic>{
'type': 'progress',
'payload': 42,
});
expect(event.payload, <String, dynamic>{'value': 42});
});
});
group('Ble models', () {
test('BleDevice stores constructor fields', () {
const device = BleDevice(name: 'Showen', id: 'dev-1', rssi: -48);
expect(device.name, 'Showen');
expect(device.id, 'dev-1');
expect(device.rssi, -48);
});
test('BleStatus parses json and raw json', () {
final status = BleStatus.fromJson(const <String, dynamic>{
'ok': true,
'action': 'provision',
'state': 'queued',
});
final raw = BleStatus.fromRawJson(
'{"ok":false,"action":"scan","error":"failed"}',
);
expect(status.isQueued, isTrue);
expect(status.message, 'queued');
expect(raw.isSuccess, isFalse);
expect(raw.message, 'failed');
});
});
group('BleServiceStatus', () {
test('initial and fromJson', () {
final initial = BleServiceStatus.initial();
final status = BleServiceStatus.fromJson(const <String, dynamic>{
'running': true,
'embedded': true,
'device_name': 'Showen BLE',
});
expect(initial.running, isFalse);
expect(initial.embedded, isFalse);
expect(status.running, isTrue);
expect(status.embedded, isTrue);
expect(status.deviceName, 'Showen BLE');
});
});
group('DeviceStatus', () {
test('initial and copyWith preserve nested models', () {
final updated = DeviceStatus.initial().copyWith(
connected: true,
connectionType: 'wifi',
deviceName: 'Showen Box',
ipAddress: '192.168.1.20',
playerStatus: PlayerStatus.initial().copyWith(running: true),
wifiStatus: WifiStatus.fromJson(
const <String, dynamic>{'connected': true, 'ssid': 'Office'},
),
bleStatus: BleServiceStatus.fromJson(
const <String, dynamic>{'running': true, 'embedded': false},
),
);
expect(updated.connected, isTrue);
expect(updated.connectionType, 'wifi');
expect(updated.deviceName, 'Showen Box');
expect(updated.ipAddress, '192.168.1.20');
expect(updated.playerStatus?.running, isTrue);
expect(updated.wifiStatus?.ssid, 'Office');
expect(updated.bleStatus?.running, isTrue);
});
});
group('PlayerStatus', () {
test('fromJson and toJson round trip', () {
final status = PlayerStatus.fromJson(const <String, dynamic>{
'running': true,
'paused': false,
'in_transition': true,
'current_index': 3,
'playlist_length': 9,
'current_video': 'intro.mp4',
});
expect(status.toJson(), <String, dynamic>{
'running': true,
'paused': false,
'in_transition': true,
'current_index': 3,
'playlist_length': 9,
'current_video': 'intro.mp4',
});
expect(status.copyWith(paused: true).paused, isTrue);
});
});
group('VideoItem', () {
test('fromJson parses file metadata', () {
final video = VideoItem.fromJson(const <String, dynamic>{
'name': 'demo.mp4',
'size': 3145728,
});
expect(video.name, 'demo.mp4');
expect(video.size, 3145728);
expect(video.sizeLabel, '3.0 MB');
});
});
group('WifiNetwork', () {
test('fromJson parses network metadata', () {
final network = WifiNetwork.fromJson(const <String, dynamic>{
'ssid': 'ShowenLab',
'signal': -51,
'security': 'WPA2',
});
expect(network.ssid, 'ShowenLab');
expect(network.signalLabel, '-51 dBm');
expect(network.security, 'WPA2');
});
});
group('WifiStatus', () {
test('disconnected and fromJson', () {
final disconnected = WifiStatus.disconnected();
final status = WifiStatus.fromJson(const <String, dynamic>{
'connected': true,
'ssid': 'ShowenLab',
'ip': '192.168.1.10',
});
expect(disconnected.connected, isFalse);
expect(status.connected, isTrue);
expect(status.ssid, 'ShowenLab');
expect(status.ip, '192.168.1.10');
});
});
}