// test/metadata_normalizer_test.dart import 'package:flutter_test/flutter_test.dart'; import 'package:qingting_player/metadata/metadata_model.dart'; import 'package:qingting_player/metadata/metadata_normalizer.dart'; void main() { final normalizer = MetadataNormalizer(); RawMetadata raw({ String title = '', String artist = '', String album = '', int year = 0, }) => RawMetadata(title: title, artist: artist, album: album, year: year); group('normalize 字段来源', () { test('标签齐全时三个字段都标记为来自标签', () { final n = normalizer.normalize( raw(title: '夜曲', artist: '周杰伦', album: '十一月的萧邦'), fileName: 'track01.mp3', filePath: '/音乐/周杰伦/track01.mp3', ); expect(n.title, '夜曲'); expect(n.artist, '周杰伦'); expect(n.album, '十一月的萧邦'); expect(n.titleFromTag, isTrue); expect(n.artistFromTag, isTrue); expect(n.albumFromTag, isTrue); }); test('没有标签时回退到文件名与目录', () { final n = normalizer.normalize( raw(), fileName: '晴天.mp3', filePath: '/音乐/周杰伦/晴天.mp3', ); expect(n.title, '晴天'); expect(n.artist, '周杰伦'); expect(n.titleFromTag, isFalse); expect(n.artistFromTag, isFalse); }); }); group('evaluate 置信度分级', () { NormalizedMetadata norm({ required String title, required String artist, String album = '', bool titleTag = true, bool artistTag = true, bool albumTag = false, }) => NormalizedMetadata( title: title, artist: artist, album: album, titleFromTag: titleTag, artistFromTag: artistTag, albumFromTag: albumTag, ); test('标题 + 艺术家 + 专辑 → 0.90', () { final c = normalizer.evaluate( norm(title: '夜曲', artist: '周杰伦', album: '十一月的萧邦', albumTag: true), const [], ); expect(c.confidence, closeTo(0.90, 0.001)); }); test('只有标题和艺术家 → 0.80', () { final c = normalizer.evaluate(norm(title: '夜曲', artist: '周杰伦'), const []); expect(c.confidence, closeTo(0.80, 0.001)); }); test('只有文件名(无标签)→ 0.35,低于阈值', () { final c = normalizer.evaluate( norm(title: 'track01', artist: '未知艺术家', titleTag: false, artistTag: false), const [], ); expect(c.confidence, closeTo(0.35, 0.001)); expect(c.confidence < 0.6, isTrue); }); test('历史一致性加权:同艺人 ≥2 条 → +0.05', () { final history = [ {'artist': '周杰伦', 'album': ''}, {'artist': '周杰伦', 'album': ''}, ]; final c = normalizer.evaluate( norm(title: '夜曲', artist: '周杰伦'), history, ); expect(c.confidence, closeTo(0.85, 0.001)); expect(c.evidence['artist_history'], 0.05); }); test('证据可解释:每一项加分都有记录', () { final c = normalizer.evaluate( norm(title: '夜曲', artist: '周杰伦', album: '十一月的萧邦', albumTag: true), const [], ); expect(c.evidence.containsKey('base'), isTrue); expect(c.evidence.containsKey('title_from_tag'), isTrue); expect(c.evidence.containsKey('artist_from_tag'), isTrue); expect(c.evidence.containsKey('album'), isTrue); }); }); group('decide 阈值', () { test('高于阈值时 source=normalized', () { final c = normalizer.evaluate( const NormalizedMetadata( title: '夜曲', artist: '周杰伦', titleFromTag: true, artistFromTag: true, ), const [], ); final f = normalizer.decide(c); expect(f.source, 'normalized'); expect(f.title, '夜曲'); }); test('低于阈值时 source=pending', () { final c = normalizer.evaluate( const NormalizedMetadata( title: 'track01', artist: '未知艺术家', titleFromTag: false, artistFromTag: false, ), const [], ); final f = normalizer.decide(c); expect(f.source, 'pending'); }); }); }