using AvParser.Core.Proxies; using AvParser.Infrastructure.Proxies; namespace AvParser.Infrastructure.Tests; public class ProxiflyFeedTests { /// Captured verbatim from the live feed, so the schema is pinned by a real payload. private const string Sample = """ [ { "proxy": "socks5://208.102.51.6:58208", "protocol": "socks5", "ip": "208.102.51.6", "port": 58208, "https": false, "anonymity": "transparent", "score": 1, "geolocation": { "country": "US", "city": "Unknown" } }, { "proxy": "http://45.61.98.1:3128", "protocol": "http", "ip": "45.61.98.1", "port": 3128, "https": true, "anonymity": "elite", "score": 4, "geolocation": { "country": "DE", "city": "Berlin" } } ] """; [Fact] public void Parses_the_published_schema() { var endpoints = ProxiflyProxySource.ParseFeed(Sample); endpoints.Count.ShouldBe(2); var socks = endpoints[0]; socks.Protocol.ShouldBe(ProxyProtocol.Socks5); socks.Host.ShouldBe("208.102.51.6"); socks.Port.ShouldBe(58208); socks.Country.ShouldBe("US"); socks.Anonymity.ShouldBe(ProxyAnonymity.Transparent); socks.Score.ShouldBe(1); } [Fact] public void Keeps_a_real_city_and_drops_the_Unknown_placeholder() { var endpoints = ProxiflyProxySource.ParseFeed(Sample); // The feed writes the literal string "Unknown" rather than omitting the field; showing // that in the UI would be worse than showing nothing. endpoints[0].City.ShouldBeNull(); endpoints[1].City.ShouldBe("Berlin"); } [Fact] public void An_empty_feed_is_not_an_error() => ProxiflyProxySource.ParseFeed("[]").ShouldBeEmpty(); [Fact] public void Falls_back_to_the_proxy_field_when_the_parts_are_missing() { var endpoint = ProxiflyProxySource.ToEndpoint( new ProxiflyRecord { Proxy = "socks4://9.9.9.9:1080", Protocol = "socks4" } ); endpoint.ShouldNotBeNull(); endpoint.Protocol.ShouldBe(ProxyProtocol.Socks4); endpoint.Port.ShouldBe(1080); } [Fact] public void Skips_a_record_it_cannot_make_sense_of() => ProxiflyProxySource .ToEndpoint( new ProxiflyRecord { Protocol = "gopher", Ip = "1.2.3.4", Port = 80, } ) .ShouldBeNull(); [Fact] public void Skips_a_record_with_an_impossible_port() => ProxiflyProxySource .ToEndpoint( new ProxiflyRecord { Protocol = "http", Ip = "1.2.3.4", Port = 0, } ) .ShouldBeNull(); [Fact] public void A_malformed_row_does_not_take_the_whole_feed_down() { const string mixed = """ [ { "protocol": "http", "ip": "1.2.3.4", "port": 8080 }, { "protocol": "nonsense", "ip": "5.6.7.8", "port": 9 }, { "protocol": "socks5", "ip": "9.9.9.9", "port": 1080 } ] """; ProxiflyProxySource.ParseFeed(mixed).Count.ShouldBe(2); } }