Skip to content

Commit

Permalink
Merge pull request #32 from skuill/feature/30_async_tests
Browse files Browse the repository at this point in the history
Bundle #30 #31. Fixed SongLyrics provider encoded symbols in text and added integration tests
  • Loading branch information
skuill authored Dec 12, 2024
2 parents bd6ed76 + 20b2093 commit d79ec03
Show file tree
Hide file tree
Showing 15 changed files with 461 additions and 4 deletions.
6 changes: 3 additions & 3 deletions LyricsScraperNET.Client/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ static async Task Main()
//// How to configure for ASP.NET applications:
var result = ExampleWithHostConfiguration(artistToSearch, songToSearch);

//// How to configure for a certain external provider:
//var result = ExampleWithCertainProvider(artistToSearch, songToSearch);
//// How to configure for a certain external provider using explicit instantiation:
//var result = ExampleWithExplicitInstantiation(artistToSearch, songToSearch);

//// Checking that something was found. The response can be empty in two cases:
//// 1) A search error occurred. Detailed information can be found in the logs or in response fields like 'ResponseStatusCode' and 'ResponseMessage'.
Expand Down Expand Up @@ -114,7 +114,7 @@ private static SearchResult ExampleWithHostConfiguration(string artistToSearch,
/// <param name="artistToSearch">artist name to search</param>
/// <param name="songToSearch">song name to search</param>
/// <returns>lyrics text</returns>
private static SearchResult ExampleWithCertainProvider(string artistToSearch, string songToSearch)
private static SearchResult ExampleWithExplicitInstantiation(string artistToSearch, string songToSearch)
{
//// Create instance of LyricScraperClient with all available lyrics providers
ILyricsScraperClient lyricsScraperClient
Expand Down
15 changes: 15 additions & 0 deletions LyricsScraperNET/Providers/SongLyrics/SongLyricsParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using LyricsScraperNET.Providers.Abstract;
using System.Net;

namespace LyricsScraperNET.Providers.SongLyrics
{
internal sealed class SongLyricsParser : IExternalProviderLyricParser
{
public string Parse(string lyric)
{
lyric = WebUtility.HtmlDecode(lyric);

return lyric?.Trim();

Check warning on line 12 in LyricsScraperNET/Providers/SongLyrics/SongLyricsParser.cs

View workflow job for this annotation

GitHub Actions / lyrics_scraper_net-cicd

Possible null reference return.
}
}
}
5 changes: 4 additions & 1 deletion LyricsScraperNET/Providers/SongLyrics/SongLyricsProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public sealed class SongLyricsProvider : ExternalProviderBase
public SongLyricsProvider()

Check warning on line 37 in LyricsScraperNET/Providers/SongLyrics/SongLyricsProvider.cs

View workflow job for this annotation

GitHub Actions / lyrics_scraper_net-cicd

Non-nullable field '_logger' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.

Check warning on line 37 in LyricsScraperNET/Providers/SongLyrics/SongLyricsProvider.cs

View workflow job for this annotation

GitHub Actions / lyrics_scraper_net-cicd

Non-nullable field '_logger' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
{
WebClient = new NetHttpClient();
Parser = new SongLyricsParser();
Options = new SongLyricsOptions() { Enabled = true };
_uriConverter = new SongLyricsUriConverter();
}
Expand Down Expand Up @@ -146,7 +147,9 @@ private SearchResult GetParsedLyricFromHtmlPageBody(Uri uri, string htmlPageBody
|| string.Equals(lyricsContainerNode.InnerText, $"[{InstrumentalLyricText}]", StringComparison.OrdinalIgnoreCase))
return new SearchResult(Models.ExternalProviderType.SongLyrics).AddInstrumental(true);

return new SearchResult(lyricsContainerNode.InnerText, Models.ExternalProviderType.SongLyrics);
var parsedLyric = Parser.Parse(lyricsContainerNode.InnerText);

return new SearchResult(parsedLyric, Models.ExternalProviderType.SongLyrics);
}
}
}
58 changes: 58 additions & 0 deletions Tests/LyricsScraperNET.IntegrationTest/LyricsScraperClientTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using LyricsScraperNET.Models.Requests;
using LyricsScraperNET.Models.Responses;
using System.Threading.Tasks;
using Xunit;

namespace LyricsScraperNET.IntegrationTest
{
public class LyricsScraperClientTests
{
[Fact]
public void SearchLyric_WithDefaultExample_ShouldReturnSuccessfulSearchResult()
{
// Arrange
string artistToSearch = "Parkway Drive";
string songToSearch = "Idols And Anchors";
ILyricsScraperClient lyricsScraperClient
= new LyricsScraperClient()
.WithAllProviders();

var searchRequest = new ArtistAndSongSearchRequest(artistToSearch, songToSearch);

// Act
var searchResult = lyricsScraperClient.SearchLyric(searchRequest);

// Assert
Assert.NotNull(searchResult);
Assert.False(searchResult.IsEmpty());
Assert.Equal(ResponseStatusCode.Success, searchResult.ResponseStatusCode);
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.NotNull(searchResult.LyricText);
Assert.False(searchResult.Instrumental);
}

[Fact]
public async Task SearchLyricAsync_WithDefaultExample_ShouldReturnSuccessfulSearchResult()
{
// Arrange
string artistToSearch = "Parkway Drive";
string songToSearch = "Idols And Anchors";
ILyricsScraperClient lyricsScraperClient
= new LyricsScraperClient()
.WithAllProviders();

var searchRequest = new ArtistAndSongSearchRequest(artistToSearch, songToSearch);

// Act
var searchResult = await lyricsScraperClient.SearchLyricAsync(searchRequest);

// Assert
Assert.NotNull(searchResult);
Assert.False(searchResult.IsEmpty());
Assert.Equal(ResponseStatusCode.Success, searchResult.ResponseStatusCode);
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.NotNull(searchResult.LyricText);
Assert.False(searchResult.Instrumental);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@
<None Update="Providers\SongLyrics\instrumental_test_data.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Providers\SongLyrics\Resources\Lyrics_Result_02.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Providers\SongLyrics\Resources\Lyrics_Result_01.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
using LyricsScraperNET.Providers.Models;
using LyricsScraperNET.TestShared.Providers;
using LyricsScraperNET.UnitTest.TestModel;
using System.Threading.Tasks;
using Xunit;

namespace LyricsScraperNET.IntegrationTest.Providers.AZLyrics
{
public class AZLyricsProviderTest : ProviderTestBase
{
#region sync

[Theory]
[MemberData(nameof(GetTestData), parameters: "Providers\\AZLyrics\\lyric_test_data.json")]
public void SearchLyric_IntegrationDynamicData_Success(LyricsTestData testData)
Expand Down Expand Up @@ -49,5 +52,51 @@ public void SearchLyric_NotExistsLyrics_ShouldReturnNoDataFoundStatus(string art
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.False(searchResult.Instrumental);
}

#endregion

#region async

[Theory]
[MemberData(nameof(GetTestData), parameters: "Providers\\AZLyrics\\lyric_test_data.json")]
public async Task SearchLyricAsync_IntegrationDynamicData_Success(LyricsTestData testData)
{
// Arrange
var lyricsClient = new AZLyricsProvider();
SearchRequest searchRequest = CreateSearchRequest(testData);

// Act
var searchResult = await lyricsClient.SearchLyricAsync(searchRequest);

// Assert
Assert.NotNull(searchResult);
Assert.False(searchResult.IsEmpty());
Assert.Equal(ResponseStatusCode.Success, searchResult.ResponseStatusCode);
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.Equal(ExternalProviderType.AZLyrics, searchResult.ExternalProviderType);
Assert.Equal(testData.LyricResultData.Replace("\r\n", "\n"), searchResult.LyricText.Replace("\r\n", "\n"));
}

[Theory]
[InlineData("asdfasdfasdfasdf", "asdfasdfasdfasdf")]
public async Task SearchLyricAsync_NotExistsLyrics_ShouldReturnNoDataFoundStatus(string artist, string song)
{
// Arrange
var lyricsClient = new AZLyricsProvider();
var searchRequest = new ArtistAndSongSearchRequest(artist, song);

// Act
var searchResult = await lyricsClient.SearchLyricAsync(searchRequest);

// Assert
Assert.NotNull(searchResult);
Assert.True(searchResult.IsEmpty());
Assert.Equal(ResponseStatusCode.NoDataFound, searchResult.ResponseStatusCode);
Assert.Equal(ExternalProviderType.AZLyrics, searchResult.ExternalProviderType);
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.False(searchResult.Instrumental);
}

#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@
"ArtistName": "Parkway Drive",
"SongName": "Idols and Anchors",
"SongUri": null
},
{
"LyricResultPath": "Providers/AZLyrics/Resources/Lyrics_Result_01.txt",
"ArtistName": null,
"SongName": null,
"SongUri": "https://www.azlyrics.com/lyrics/parkwaydrive/wishingwells.html"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
using LyricsScraperNET.Providers.Models;
using LyricsScraperNET.TestShared.Providers;
using LyricsScraperNET.UnitTest.TestModel;
using System.Threading.Tasks;
using Xunit;

namespace LyricsScraperNET.IntegrationTest.Providers.Genius
{
public class GeniusProviderTest : ProviderTestBase
{
#region sync

[Theory]
[MemberData(nameof(GetTestData), parameters: "Providers\\Genius\\lyric_test_data.json")]
public void SearchLyric_IntegrationDynamicData_Success(LyricsTestData testData)
Expand Down Expand Up @@ -70,5 +73,72 @@ public void SearchLyric_NotExistsLyrics_ShouldReturnNoDataFoundStatus(string art
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.False(searchResult.Instrumental);
}

#endregion

#region async

[Theory]
[MemberData(nameof(GetTestData), parameters: "Providers\\Genius\\lyric_test_data.json")]
public async Task SearchLyricAsync_IntegrationDynamicData_Success(LyricsTestData testData)
{
// Arrange
var lyricsClient = new GeniusProvider();
SearchRequest searchRequest = CreateSearchRequest(testData);

// Act
var searchResult = await lyricsClient.SearchLyricAsync(searchRequest);

// Assert
Assert.NotNull(searchResult);
Assert.False(searchResult.IsEmpty());
Assert.Equal(ResponseStatusCode.Success, searchResult.ResponseStatusCode);
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.Equal(ExternalProviderType.Genius, searchResult.ExternalProviderType);
Assert.Equal(testData.LyricResultData.Replace("\r\n", "\n"), searchResult.LyricText.Replace("\r\n", "\n"));
Assert.False(searchResult.Instrumental);
}

[Theory]
[MemberData(nameof(GetTestData), parameters: "Providers\\Genius\\instrumental_test_data.json")]
public async Task SearchLyricAsync_UnitDynamicData_Instrumental(LyricsTestData testData)
{
// Arrange
var lyricsClient = new GeniusProvider();
SearchRequest searchRequest = CreateSearchRequest(testData);

// Act
var searchResult = await lyricsClient.SearchLyricAsync(searchRequest);

// Assert
Assert.NotNull(searchResult);
Assert.True(searchResult.IsEmpty());
Assert.Equal(ResponseStatusCode.Success, searchResult.ResponseStatusCode);
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.Equal(ExternalProviderType.Genius, searchResult.ExternalProviderType);
Assert.True(searchResult.Instrumental);
}

[Theory]
[InlineData("asdfasdfasdfasdf", "asdfasdfasdfasdf")]
public async Task SearchLyricAsync_NotExistsLyrics_ShouldReturnNoDataFoundStatus(string artist, string song)
{
// Arrange
var lyricsClient = new GeniusProvider();
var searchRequest = new ArtistAndSongSearchRequest(artist, song);

// Act
var searchResult = await lyricsClient.SearchLyricAsync(searchRequest);

// Assert
Assert.NotNull(searchResult);
Assert.True(searchResult.IsEmpty());
Assert.Equal(ResponseStatusCode.NoDataFound, searchResult.ResponseStatusCode);
Assert.Equal(ExternalProviderType.Genius, searchResult.ExternalProviderType);
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.False(searchResult.Instrumental);
}

#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@
"ArtistName": "Iron Maiden",
"SongName": "The Number of the Beast",
"SongUri": null
},
{
"LyricResultPath": "Providers/Genius/Resources/Lyrics_Result_01.txt",
"ArtistName": null,
"SongName": null,
"SongUri": "https://genius.com/Parkway-drive-idols-and-anchors-lyrics"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
using LyricsScraperNET.Providers.Models;
using LyricsScraperNET.TestShared.Providers;
using LyricsScraperNET.UnitTest.TestModel;
using System.Threading.Tasks;
using Xunit;

namespace LyricsScraperNET.IntegrationTest.Providers.LyricFind
{
public class LyricFindProviderTest : ProviderTestBase
{
#region sync

[Theory]
[MemberData(nameof(GetTestData), parameters: "Providers\\LyricFind\\lyric_test_data.json")]
public void SearchLyric_IntegrationDynamicData_Success(LyricsTestData testData)
Expand Down Expand Up @@ -70,5 +73,72 @@ public void SearchLyric_NotExistsLyrics_ShouldReturnNoDataFoundStatus(string art
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.False(searchResult.Instrumental);
}

#endregion

#region async

[Theory]
[MemberData(nameof(GetTestData), parameters: "Providers\\LyricFind\\lyric_test_data.json")]
public async Task SearchLyricAsync_IntegrationDynamicData_Success(LyricsTestData testData)
{
// Arrange
var lyricsClient = new LyricFindProvider();
SearchRequest searchRequest = CreateSearchRequest(testData);

// Act
var searchResult = await lyricsClient.SearchLyricAsync(searchRequest);

// Assert
Assert.NotNull(searchResult);
Assert.False(searchResult.IsEmpty());
Assert.Equal(ResponseStatusCode.Success, searchResult.ResponseStatusCode);
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.Equal(ExternalProviderType.LyricFind, searchResult.ExternalProviderType);
Assert.Equal(testData.LyricResultData.Replace("\r\n", "\n"), searchResult.LyricText.Replace("\r\n", "\n"));
Assert.False(searchResult.Instrumental);
}

[Theory]
[MemberData(nameof(GetTestData), parameters: "Providers\\LyricFind\\instrumental_test_data.json")]
public async Task SearchLyricAsync_IntegrationDynamicData_Instrumental(LyricsTestData testData)
{
// Arrange
var lyricsClient = new LyricFindProvider();
SearchRequest searchRequest = CreateSearchRequest(testData);

// Act
var searchResult = await lyricsClient.SearchLyricAsync(searchRequest);

// Assert
Assert.NotNull(searchResult);
Assert.True(searchResult.IsEmpty());
Assert.Equal(ResponseStatusCode.Success, searchResult.ResponseStatusCode);
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.Equal(ExternalProviderType.LyricFind, searchResult.ExternalProviderType);
Assert.True(searchResult.Instrumental);
}

[Theory]
[InlineData("asdfasdfasdfasdf", "asdfasdfasdfasdf")]
public async Task SearchLyricAsync_NotExistsLyrics_ShouldReturnNoDataFoundStatus(string artist, string song)
{
// Arrange
var lyricsClient = new LyricFindProvider();
var searchRequest = new ArtistAndSongSearchRequest(artist, song);

// Act
var searchResult = await lyricsClient.SearchLyricAsync(searchRequest);

// Assert
Assert.NotNull(searchResult);
Assert.True(searchResult.IsEmpty());
Assert.Equal(ResponseStatusCode.NoDataFound, searchResult.ResponseStatusCode);
Assert.Equal(ExternalProviderType.LyricFind, searchResult.ExternalProviderType);
Assert.True(string.IsNullOrEmpty(searchResult.ResponseMessage));
Assert.False(searchResult.Instrumental);
}

#endregion
}
}
Loading

0 comments on commit d79ec03

Please sign in to comment.