重构ClipboardRecordingModel以支持可选的时间戳,并更新相关测试以改进JSON解析和验证。
This commit is contained in:
@@ -19,8 +19,8 @@ class ClipboardRecordingModel {
|
|||||||
factory ClipboardRecordingModel.fromJson(Map<String, dynamic> json) {
|
factory ClipboardRecordingModel.fromJson(Map<String, dynamic> json) {
|
||||||
return ClipboardRecordingModel(
|
return ClipboardRecordingModel(
|
||||||
title: _readString(json, 'title'),
|
title: _readString(json, 'title'),
|
||||||
startTimestamp: _readInt(json, 'startTimestamp'),
|
startTimestamp: _readOptionalInt(json, 'startTimestamp'),
|
||||||
endTimestamp: _readInt(json, 'endTimestamp'),
|
endTimestamp: _readOptionalInt(json, 'endTimestamp'),
|
||||||
address: _readString(json, 'address'),
|
address: _readString(json, 'address'),
|
||||||
filename: _readOptionalString(json, 'filename'),
|
filename: _readOptionalString(json, 'filename'),
|
||||||
);
|
);
|
||||||
@@ -52,8 +52,9 @@ class ClipboardRecordingModel {
|
|||||||
throw FormatException('Clipboard field "$key" must be a String.');
|
throw FormatException('Clipboard field "$key" must be a String.');
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _readInt(Map<String, dynamic> json, String key) {
|
static int? _readOptionalInt(Map<String, dynamic> json, String key) {
|
||||||
final value = json[key];
|
final value = json[key];
|
||||||
|
if (value == null) return null;
|
||||||
if (value is int) return value;
|
if (value is int) return value;
|
||||||
throw FormatException('Clipboard field "$key" must be an int.');
|
throw FormatException('Clipboard field "$key" must be an int.');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ class RecordingViewModel extends StateNotifier<RecordingModel> {
|
|||||||
RecordingModel(
|
RecordingModel(
|
||||||
clipboardRecordingModel: ClipboardRecordingModel(
|
clipboardRecordingModel: ClipboardRecordingModel(
|
||||||
title: '',
|
title: '',
|
||||||
startTimestamp: 0,
|
|
||||||
endTimestamp: 0,
|
|
||||||
address: '',
|
address: '',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -40,8 +38,6 @@ class RecordingViewModel extends StateNotifier<RecordingModel> {
|
|||||||
|
|
||||||
static final _defaultClipboard = ClipboardRecordingModel(
|
static final _defaultClipboard = ClipboardRecordingModel(
|
||||||
title: '',
|
title: '',
|
||||||
startTimestamp: 0,
|
|
||||||
endTimestamp: 0,
|
|
||||||
address: '',
|
address: '',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,21 @@ void main() {
|
|||||||
expect(model.toJson(), clipboardJson);
|
expect(model.toJson(), clipboardJson);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('parses JSON without optional timestamps', () {
|
||||||
|
final json = {
|
||||||
|
'title': '郑昌梦 丨黄伟依 空中格斗赛 小学组',
|
||||||
|
'address': '广东省汕头市番禺区青蓝街 111 号',
|
||||||
|
'filename': '郑昌梦_黄伟依_6月3日测试-1_空中格斗赛',
|
||||||
|
};
|
||||||
|
final model = ClipboardRecordingModel.fromJson(json);
|
||||||
|
|
||||||
|
expect(model.title, json['title']);
|
||||||
|
expect(model.address, json['address']);
|
||||||
|
expect(model.filename, json['filename']);
|
||||||
|
expect(model.startTimestamp, isNull);
|
||||||
|
expect(model.endTimestamp, isNull);
|
||||||
|
});
|
||||||
|
|
||||||
test('parses optional filename from mini program JSON', () {
|
test('parses optional filename from mini program JSON', () {
|
||||||
final json = {
|
final json = {
|
||||||
...clipboardJson,
|
...clipboardJson,
|
||||||
@@ -41,7 +56,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('throws FormatException when required field has wrong type', () {
|
test('throws FormatException when optional int field has wrong type', () {
|
||||||
final json = {...clipboardJson, 'startTimestamp': '1717334400'};
|
final json = {...clipboardJson, 'startTimestamp': '1717334400'};
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -49,5 +64,14 @@ void main() {
|
|||||||
throwsA(isA<FormatException>()),
|
throwsA(isA<FormatException>()),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('throws FormatException when required address is missing', () {
|
||||||
|
final json = Map<String, dynamic>.from(clipboardJson)..remove('address');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
() => ClipboardRecordingModel.fromJson(json),
|
||||||
|
throwsA(isA<FormatException>()),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('returns invalid when clipboard JSON misses required fields', () async {
|
test('returns invalid when clipboard JSON misses required address', () async {
|
||||||
await setClipboardText('{"title":"王东方 丨李想 空中格斗赛"}');
|
await setClipboardText('{"title":"王东方 丨李想 空中格斗赛"}');
|
||||||
final container = ProviderContainer();
|
final container = ProviderContainer();
|
||||||
addTearDown(container.dispose);
|
addTearDown(container.dispose);
|
||||||
@@ -121,6 +121,31 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'updates state when clipboard omits optional timestamps',
|
||||||
|
() async {
|
||||||
|
await setClipboardText(
|
||||||
|
'{"title":"郑昌梦 丨黄伟依 空中格斗赛 小学组","address":"广东省汕头市番禺区青蓝街 111 号","filename":"郑昌梦_黄伟依_6月3日测试-1_空中格斗赛"}',
|
||||||
|
);
|
||||||
|
final container = ProviderContainer();
|
||||||
|
addTearDown(container.dispose);
|
||||||
|
|
||||||
|
final result = await container
|
||||||
|
.read(recordingViewModelProvider.notifier)
|
||||||
|
.getClipboardContent();
|
||||||
|
|
||||||
|
expect(result, ClipboardReadResult.success);
|
||||||
|
final model = container.read(recordingViewModelProvider);
|
||||||
|
expect(model.hasValidClipboardInfo, isTrue);
|
||||||
|
expect(model.clipboardRecordingModel.startTimestamp, isNull);
|
||||||
|
expect(model.clipboardRecordingModel.endTimestamp, isNull);
|
||||||
|
expect(
|
||||||
|
model.clipboardRecordingModel.filename,
|
||||||
|
'郑昌梦_黄伟依_6月3日测试-1_空中格斗赛',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
test('returns invalid when clipboard JSON has wrong field type', () async {
|
test('returns invalid when clipboard JSON has wrong field type', () async {
|
||||||
await setClipboardText(
|
await setClipboardText(
|
||||||
'{"title":"王东方 丨李想 空中格斗赛","startTimestamp":"1717334400","endTimestamp":1717334400,"address":"广州市番禺区·粤港澳大湾区青年人才双创小镇"}',
|
'{"title":"王东方 丨李想 空中格斗赛","startTimestamp":"1717334400","endTimestamp":1717334400,"address":"广州市番禺区·粤港澳大湾区青年人才双创小镇"}',
|
||||||
|
|||||||
Reference in New Issue
Block a user