using System.Reflection; using LiveRecorder.Application.Abstractions.Platforms; using LiveRecorder.Application.Services; using LiveRecorder.Domain.Enums; namespace LiveRecorder.Tests; public sealed class LiveRoomServiceLocalParsingTests { [Theory] [InlineData("https://www.huya.com/660000", LivePlatformType.Huya, "660000", "https://www.huya.com/660000")] [InlineData("https://www.douyu.com/9999", LivePlatformType.Douyu, "9999", "https://www.douyu.com/9999")] [InlineData("https://live.kuaishou.com/u/3xabc123", LivePlatformType.Kuaishou, "u/3xabc123", "https://live.kuaishou.com/u/3xabc123")] [InlineData("https://www.tiktok.com/@creator/live", LivePlatformType.TikTok, "creator", "https://www.tiktok.com/@creator/live")] [InlineData("https://www.xiaohongshu.com/live/room-100", LivePlatformType.Xiaohongshu, "live/room-100", "https://www.xiaohongshu.com/live/room-100")] [InlineData("https://www.youtube.com/watch?v=abcDEF12345", LivePlatformType.YouTube, "abcDEF12345", "https://www.youtube.com/watch?v=abcDEF12345")] [InlineData("https://www.twitch.tv/some_channel", LivePlatformType.Twitch, "some_channel", "https://www.twitch.tv/some_channel")] [InlineData("https://www.pandalive.co.kr/live/room77", LivePlatformType.PandaTV, "live/room77", "https://www.pandalive.co.kr/live/room77")] [InlineData("https://www.miguvideo.com/live/8888", LivePlatformType.Migu, "live/8888", "https://www.miguvideo.com/live/8888")] public void ParseRoomLocally_parses_supported_urls( string input, LivePlatformType expectedPlatform, string expectedRoomId, string expectedNormalizedUrl) { var parsed = ParseRoomLocally(input, platformOverride: null); Assert.Equal(expectedPlatform, parsed.PlatformType); Assert.Equal(expectedRoomId, parsed.RoomId); Assert.Equal(expectedNormalizedUrl, parsed.NormalizedUrl); } [Theory] [InlineData("some_channel", LivePlatformType.Twitch, "some_channel", "https://www.twitch.tv/some_channel")] [InlineData("abcDEF12345", LivePlatformType.YouTube, "abcDEF12345", "https://www.youtube.com/watch?v=abcDEF12345")] public void ParseRoomLocally_supports_direct_ids_with_platform_override( string input, LivePlatformType platformOverride, string expectedRoomId, string expectedNormalizedUrl) { var parsed = ParseRoomLocally(input, platformOverride); Assert.Equal(platformOverride, parsed.PlatformType); Assert.Equal(expectedRoomId, parsed.RoomId); Assert.Equal(expectedNormalizedUrl, parsed.NormalizedUrl); } [Fact] public void ParseRoomLocally_requires_detection_when_platform_cannot_be_inferred() { var exception = Assert.Throws(() => ParseRoomLocally("creator-room", platformOverride: null)); Assert.Contains("Unable to infer the platform", exception.Message); } private static ParsedLiveRoom ParseRoomLocally(string input, LivePlatformType? platformOverride) { var method = typeof(LiveRoomService).GetMethod("ParseRoomLocally", BindingFlags.NonPublic | BindingFlags.Static) ?? throw new InvalidOperationException("ParseRoomLocally reflection lookup failed."); try { return (ParsedLiveRoom)(method.Invoke(null, [input, platformOverride]) ?? throw new InvalidOperationException("ParseRoomLocally returned null.")); } catch (TargetInvocationException ex) when (ex.InnerException is not null) { throw ex.InnerException; } } }