升级 Gradle → 8.14、AGP → 8.11、Kotlin → 2.2.20 JVM 堆降到 -Xmx4G
This commit is contained in:
@@ -71,7 +71,7 @@ void main() {
|
||||
});
|
||||
|
||||
group('iOS permission configuration', () {
|
||||
test('Podfile enables camera and microphone permission macros', () {
|
||||
test('Podfile enables camera, microphone and photos permission macros', () {
|
||||
final podfile = File('ios/Podfile').readAsStringSync();
|
||||
|
||||
expect(
|
||||
@@ -80,6 +80,8 @@ void main() {
|
||||
);
|
||||
expect(podfile, contains("'PERMISSION_CAMERA=1'"));
|
||||
expect(podfile, contains("'PERMISSION_MICROPHONE=1'"));
|
||||
expect(podfile, contains("'PERMISSION_PHOTOS=1'"));
|
||||
expect(podfile, contains("'PERMISSION_PHOTOS_ADD_ONLY=1'"));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,9 +17,21 @@ void main() {
|
||||
expect(model.startTimestamp, 1717334400);
|
||||
expect(model.endTimestamp, 1717334400);
|
||||
expect(model.address, '广州市番禺区·粤港澳大湾区青年人才双创小镇');
|
||||
expect(model.filename, isNull);
|
||||
expect(model.toJson(), clipboardJson);
|
||||
});
|
||||
|
||||
test('parses optional filename from mini program JSON', () {
|
||||
final json = {
|
||||
...clipboardJson,
|
||||
'filename': '选手名称_选手ID_赛事名称_赛项',
|
||||
};
|
||||
final model = ClipboardRecordingModel.fromJson(json);
|
||||
|
||||
expect(model.filename, '选手名称_选手ID_赛事名称_赛项');
|
||||
expect(model.toJson(), json);
|
||||
});
|
||||
|
||||
test('throws FormatException when required field is missing', () {
|
||||
final json = Map<String, dynamic>.from(clipboardJson)..remove('title');
|
||||
|
||||
|
||||
69
test/features/recording/recording_display_name_test.dart
Normal file
69
test/features/recording/recording_display_name_test.dart
Normal file
@@ -0,0 +1,69 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:recording_tool/features/recording/recording_display_name.dart';
|
||||
|
||||
void main() {
|
||||
group('sanitizeRecordingBaseName', () {
|
||||
test('removes invalid path characters', () {
|
||||
expect(
|
||||
sanitizeRecordingBaseName(r'a/b:c*d?e"f<g>h|i'),
|
||||
'a_b_c_d_e_f_g_h_i',
|
||||
);
|
||||
});
|
||||
|
||||
test('returns null for blank input', () {
|
||||
expect(sanitizeRecordingBaseName(' '), isNull);
|
||||
});
|
||||
|
||||
test('truncates overly long names', () {
|
||||
final long = 'a' * 200;
|
||||
expect(sanitizeRecordingBaseName(long)!.length, 120);
|
||||
});
|
||||
});
|
||||
|
||||
group('resolveRecordingDisplayName', () {
|
||||
test('uses sanitized clipboard filename when present', () {
|
||||
expect(
|
||||
resolveRecordingDisplayName('选手名称_选手ID_赛事名称_赛项'),
|
||||
'选手名称_选手ID_赛事名称_赛项',
|
||||
);
|
||||
});
|
||||
|
||||
test('falls back to REC_ prefix when clipboard filename is empty', () {
|
||||
expect(resolveRecordingDisplayName(null), startsWith('REC_'));
|
||||
expect(resolveRecordingDisplayName(''), startsWith('REC_'));
|
||||
});
|
||||
});
|
||||
|
||||
group('withVideoExtension', () {
|
||||
test('appends mp4 on Android', () {
|
||||
expect(
|
||||
withVideoExtension('match', isIOS: false),
|
||||
'match.mp4',
|
||||
);
|
||||
});
|
||||
|
||||
test('appends mov on iOS', () {
|
||||
expect(
|
||||
withVideoExtension('match', isIOS: true),
|
||||
'match.mov',
|
||||
);
|
||||
});
|
||||
|
||||
test('keeps existing extension', () {
|
||||
expect(withVideoExtension('a.mp4', isIOS: false), 'a.mp4');
|
||||
expect(withVideoExtension('a.MOV', isIOS: true), 'a.MOV');
|
||||
});
|
||||
});
|
||||
|
||||
group('recordingFileNameForPlatform', () {
|
||||
test('combines clipboard name with platform extension', () {
|
||||
expect(
|
||||
recordingFileNameForPlatform(
|
||||
'选手名称_选手ID_赛事名称_赛项',
|
||||
isIOS: false,
|
||||
),
|
||||
'选手名称_选手ID_赛事名称_赛项.mp4',
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -8,7 +8,7 @@ void main() {
|
||||
|
||||
const defaultClipboardTitle = '';
|
||||
const validClipboardText =
|
||||
'{"title":"王东方 丨李想 空中格斗赛","startTimestamp":1717334400,"endTimestamp":1717334400,"address":"广州市番禺区·粤港澳大湾区青年人才双创小镇"}';
|
||||
'{"title":"王东方 丨李想 空中格斗赛","startTimestamp":1717334400,"endTimestamp":1717334400,"filename":"选手名称_选手ID_赛事名称_赛项","address":"广州市番禺区·粤港澳大湾区青年人才双创小镇"}';
|
||||
|
||||
Future<void> setClipboardText(String? text) async {
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
@@ -33,116 +33,128 @@ void main() {
|
||||
final container = ProviderContainer();
|
||||
addTearDown(container.dispose);
|
||||
|
||||
await container
|
||||
final result = await container
|
||||
.read(recordingViewModelProvider.notifier)
|
||||
.getClipboardContent();
|
||||
|
||||
final clipboardModel = container
|
||||
.read(recordingViewModelProvider)
|
||||
.clipboardRecordingModel;
|
||||
expect(clipboardModel.title, '王东方 丨李想 空中格斗赛');
|
||||
expect(clipboardModel.startTimestamp, 1717334400);
|
||||
expect(clipboardModel.endTimestamp, 1717334400);
|
||||
expect(clipboardModel.address, '广州市番禺区·粤港澳大湾区青年人才双创小镇');
|
||||
expect(result, ClipboardReadResult.success);
|
||||
final model = container.read(recordingViewModelProvider);
|
||||
expect(model.hasValidClipboardInfo, isTrue);
|
||||
expect(model.clipboardRecordingModel.title, '王东方 丨李想 空中格斗赛');
|
||||
expect(model.clipboardRecordingModel.startTimestamp, 1717334400);
|
||||
expect(model.clipboardRecordingModel.endTimestamp, 1717334400);
|
||||
expect(
|
||||
model.clipboardRecordingModel.address,
|
||||
'广州市番禺区·粤港澳大湾区青年人才双创小镇',
|
||||
);
|
||||
expect(
|
||||
model.clipboardRecordingModel.filename,
|
||||
'选手名称_选手ID_赛事名称_赛项',
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test('keeps default state when clipboard is empty', () async {
|
||||
test('returns empty when clipboard is empty', () async {
|
||||
await setClipboardText('');
|
||||
final container = ProviderContainer();
|
||||
addTearDown(container.dispose);
|
||||
|
||||
await container
|
||||
final result = await container
|
||||
.read(recordingViewModelProvider.notifier)
|
||||
.getClipboardContent();
|
||||
|
||||
expect(
|
||||
container
|
||||
.read(recordingViewModelProvider)
|
||||
.clipboardRecordingModel
|
||||
.title,
|
||||
defaultClipboardTitle,
|
||||
);
|
||||
expect(result, ClipboardReadResult.empty);
|
||||
final model = container.read(recordingViewModelProvider);
|
||||
expect(model.hasValidClipboardInfo, isFalse);
|
||||
expect(model.clipboardRecordingModel.title, defaultClipboardTitle);
|
||||
});
|
||||
|
||||
test('keeps default state when clipboard is not JSON', () async {
|
||||
test('returns invalid when clipboard is not JSON', () async {
|
||||
await setClipboardText('hello');
|
||||
final container = ProviderContainer();
|
||||
addTearDown(container.dispose);
|
||||
|
||||
await container
|
||||
final result = await container
|
||||
.read(recordingViewModelProvider.notifier)
|
||||
.getClipboardContent();
|
||||
|
||||
expect(result, ClipboardReadResult.invalid);
|
||||
expect(
|
||||
container
|
||||
.read(recordingViewModelProvider)
|
||||
.clipboardRecordingModel
|
||||
.title,
|
||||
container.read(recordingViewModelProvider).clipboardRecordingModel.title,
|
||||
defaultClipboardTitle,
|
||||
);
|
||||
expect(
|
||||
container.read(recordingViewModelProvider).hasValidClipboardInfo,
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
|
||||
test('keeps default state when clipboard JSON is not an object', () async {
|
||||
test('returns invalid when clipboard JSON is not an object', () async {
|
||||
await setClipboardText('[1,2,3]');
|
||||
final container = ProviderContainer();
|
||||
addTearDown(container.dispose);
|
||||
|
||||
await container
|
||||
final result = await container
|
||||
.read(recordingViewModelProvider.notifier)
|
||||
.getClipboardContent();
|
||||
|
||||
expect(result, ClipboardReadResult.invalid);
|
||||
expect(
|
||||
container
|
||||
.read(recordingViewModelProvider)
|
||||
.clipboardRecordingModel
|
||||
.title,
|
||||
container.read(recordingViewModelProvider).clipboardRecordingModel.title,
|
||||
defaultClipboardTitle,
|
||||
);
|
||||
});
|
||||
|
||||
test(
|
||||
'keeps default state when clipboard JSON misses required fields',
|
||||
() async {
|
||||
await setClipboardText('{"title":"王东方 丨李想 空中格斗赛"}');
|
||||
final container = ProviderContainer();
|
||||
addTearDown(container.dispose);
|
||||
test('returns invalid when clipboard JSON misses required fields', () async {
|
||||
await setClipboardText('{"title":"王东方 丨李想 空中格斗赛"}');
|
||||
final container = ProviderContainer();
|
||||
addTearDown(container.dispose);
|
||||
|
||||
await container
|
||||
.read(recordingViewModelProvider.notifier)
|
||||
.getClipboardContent();
|
||||
final result = await container
|
||||
.read(recordingViewModelProvider.notifier)
|
||||
.getClipboardContent();
|
||||
|
||||
expect(
|
||||
container
|
||||
.read(recordingViewModelProvider)
|
||||
.clipboardRecordingModel
|
||||
.title,
|
||||
defaultClipboardTitle,
|
||||
);
|
||||
},
|
||||
);
|
||||
expect(result, ClipboardReadResult.invalid);
|
||||
expect(
|
||||
container.read(recordingViewModelProvider).clipboardRecordingModel.title,
|
||||
defaultClipboardTitle,
|
||||
);
|
||||
});
|
||||
|
||||
test(
|
||||
'keeps default state when clipboard JSON has wrong field type',
|
||||
() async {
|
||||
await setClipboardText(
|
||||
'{"title":"王东方 丨李想 空中格斗赛","startTimestamp":"1717334400","endTimestamp":1717334400,"address":"广州市番禺区·粤港澳大湾区青年人才双创小镇"}',
|
||||
);
|
||||
final container = ProviderContainer();
|
||||
addTearDown(container.dispose);
|
||||
test('returns invalid when clipboard JSON has wrong field type', () async {
|
||||
await setClipboardText(
|
||||
'{"title":"王东方 丨李想 空中格斗赛","startTimestamp":"1717334400","endTimestamp":1717334400,"address":"广州市番禺区·粤港澳大湾区青年人才双创小镇"}',
|
||||
);
|
||||
final container = ProviderContainer();
|
||||
addTearDown(container.dispose);
|
||||
|
||||
await container
|
||||
.read(recordingViewModelProvider.notifier)
|
||||
.getClipboardContent();
|
||||
final result = await container
|
||||
.read(recordingViewModelProvider.notifier)
|
||||
.getClipboardContent();
|
||||
|
||||
expect(
|
||||
container
|
||||
.read(recordingViewModelProvider)
|
||||
.clipboardRecordingModel
|
||||
.title,
|
||||
defaultClipboardTitle,
|
||||
);
|
||||
},
|
||||
);
|
||||
expect(result, ClipboardReadResult.invalid);
|
||||
expect(
|
||||
container.read(recordingViewModelProvider).clipboardRecordingModel.title,
|
||||
defaultClipboardTitle,
|
||||
);
|
||||
});
|
||||
|
||||
test('returns invalid when title is blank', () async {
|
||||
await setClipboardText(
|
||||
'{"title":" ","startTimestamp":1717334400,"endTimestamp":1717334400,"address":"广州市"}',
|
||||
);
|
||||
final container = ProviderContainer();
|
||||
addTearDown(container.dispose);
|
||||
|
||||
final result = await container
|
||||
.read(recordingViewModelProvider.notifier)
|
||||
.getClipboardContent();
|
||||
|
||||
expect(result, ClipboardReadResult.invalid);
|
||||
expect(
|
||||
container.read(recordingViewModelProvider).hasValidClipboardInfo,
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user