Skip to content

Commit

Permalink
Refactor ASFFreeGamesPlugin class for better design
Browse files Browse the repository at this point in the history
This commit refactors the ASFFreeGamesPlugin class to follow the
Single Responsibility Principle, which states that each class
should have one responsibility, one single purpose.

The main changes are:

- Extracted some methods from ASFFreeGamesPlugin to reduce its complexity
and increase cohesion.
- Moved some methods to other classes where they belong.
- Used more idiomatic C# patterns and features, such as string interpolation,
var keyword, using statements, null operators, LINQ, async/await, etc.
- Added XML documentation comments for public types and members.
- Added regular comments for private or complex code blocks.
- Added more unit tests to cover the refactored code.

This commit also fixes:

- Closes #28: Error when retrieving game list JSON data from reddit
- Resolves #27: Games don't add up
  • Loading branch information
maxisoft committed Aug 14, 2023
1 parent a133a81 commit 690e796
Show file tree
Hide file tree
Showing 19 changed files with 1,074 additions and 514 deletions.
46 changes: 46 additions & 0 deletions ASFFreeGames.Tests/GameIdentifierParserTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using Xunit;

namespace Maxisoft.ASF.Tests;

// A test class for the GameIdentifierParser class
public sealed class GameIdentifierParserTests {
// A test method that checks if the TryParse method can handle invalid game identifiers
[Theory]
[InlineData("a/-1")] // Negative AppID
[InlineData("s/0")] // Zero SubID
[InlineData("x/123")] // Unknown type prefix
[InlineData("app/foo")] // Non-numeric ID
[InlineData("")] // Empty query
[InlineData("/")] // Missing ID
[InlineData("a/")] // Missing AppID
[InlineData("s/")] // Missing SubID
public void TryParse_InvalidGameIdentifiers_ReturnsFalseAndDefaultResult(string query) {
// Arrange
// The default result for invalid queries
GameIdentifier defaultResult = default;

// Act and Assert
Assert.False(GameIdentifierParser.TryParse(query, out _)); // Parsing should return false
}

// A test method that checks if the TryParse method can parse valid game identifiers
[Theory]
[InlineData("a/730", 730, GameIdentifierType.App)] // AppID 730 (Counter-Strike: Global Offensive)
[InlineData("s/303386", 303386, GameIdentifierType.Sub)] // SubID 303386 (Humble Monthly - May 2017)
[InlineData("app/570", 570, GameIdentifierType.App)] // AppID 570 (Dota 2)
[InlineData("sub/29197", 29197, GameIdentifierType.Sub)] // SubID 29197 (Portal Bundle)
[InlineData("570", 570, GameIdentifierType.Sub)] // AppID 570 (Dota 2), default type is Sub
[InlineData("A/440", 440, GameIdentifierType.App)] // AppID 440 (Team Fortress 2)
[InlineData("APP/218620", 218620, GameIdentifierType.App)] // AppID 218620 (PAYDAY 2)
[InlineData("S/29197", 29197, GameIdentifierType.Sub)] // SubID 29197 (Portal Bundle)
public void TryParse_ValidGameIdentifiers_ReturnsTrueAndCorrectResult(string query, long id, GameIdentifierType type) {
// Arrange
// The expected result for the query
GameIdentifier expectedResult = new(id, type);

// Act and Assert
Assert.True(GameIdentifierParser.TryParse(query, out GameIdentifier result)); // Parsing should return true
Assert.Equal(expectedResult, result); // Result should match the expected result
}
}
80 changes: 80 additions & 0 deletions ASFFreeGames.Tests/GameIdentifierTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using Xunit;

namespace Maxisoft.ASF.Tests;

// A test class for the GameIdentifier struct
public sealed class GameIdentifierTests {
// A test method that checks if the Valid property returns true for valid game identifiers
[Theory]
[InlineData(730, GameIdentifierType.App)] // AppID 730 (Counter-Strike: Global Offensive)
[InlineData(303386, GameIdentifierType.Sub)] // SubID 303386 (Humble Monthly - May 2017)
[InlineData(570, GameIdentifierType.App)] // AppID 570 (Dota 2)
[InlineData(29197, GameIdentifierType.Sub)] // SubID 29197 (Portal Bundle)
public void Valid_ReturnsTrueForValidGameIdentifiers(long id, GameIdentifierType type) {
// Arrange
// Create a game identifier with the given id and type
GameIdentifier gameIdentifier = new(id, type);

// Act and Assert
Assert.True(gameIdentifier.Valid); // The Valid property should return true
}

// A test method that checks if the Valid property returns false for invalid game identifiers
[Theory]
[InlineData(-1, GameIdentifierType.App)] // Negative AppID
[InlineData(0, GameIdentifierType.Sub)] // Zero SubID
[InlineData(456, (GameIdentifierType) 4)] // Invalid type value
public void Valid_ReturnsFalseForInvalidGameIdentifiers(long id, GameIdentifierType type) {
// Arrange
// Create a game identifier with the given id and type
GameIdentifier gameIdentifier = new(id, type);

// Act and Assert
Assert.False(gameIdentifier.Valid); // The Valid property should return false
}

// A test method that checks if the ToString method returns the correct string representation of the game identifier
[Theory]
[InlineData(730, GameIdentifierType.App, "a/730")] // AppID 730 (Counter-Strike: Global Offensive)
[InlineData(303386, GameIdentifierType.Sub, "s/303386")] // SubID 303386 (Humble Monthly - May 2017)
[InlineData(570, GameIdentifierType.None, "570")] // AppID 570 (Dota 2), no type specified
public void ToString_ReturnsCorrectStringRepresentation(long id, GameIdentifierType type, string expectedString) {
// Arrange
// Create a game identifier with the given id and type
GameIdentifier gameIdentifier = new(id, type);

// Act and Assert
Assert.Equal(expectedString, gameIdentifier.ToString()); // The ToString method should return the expected string
}

// A test method that checks if the GetHashCode method returns the same value for equal game identifiers
[Theory]
[InlineData(730, GameIdentifierType.App)] // AppID 730 (Counter-Strike: Global Offensive)
[InlineData(303386, GameIdentifierType.Sub)] // SubID 303386 (Humble Monthly - May 2017)
[InlineData(570, GameIdentifierType.None)] // AppID 570 (Dota 2), no type specified
public void GetHashCode_ReturnsSameValueForEqualGameIdentifiers(long id, GameIdentifierType type) {
// Arrange
// Create two equal game identifiers with the given id and type
GameIdentifier gameIdentifier1 = new(id, type);
GameIdentifier gameIdentifier2 = new(id, type);

// Act and Assert
Assert.Equal(gameIdentifier1.GetHashCode(), gameIdentifier2.GetHashCode()); // The GetHashCode method should return the same value for both game identifiers
}

// A test method that checks if the GetHashCode method returns different values for unequal game identifiers
[Theory]
[InlineData(730, GameIdentifierType.App, 731, GameIdentifierType.App)] // Different AppIDs with same type
[InlineData(303386, GameIdentifierType.Sub, 303387, GameIdentifierType.Sub)] // Different SubIDs with same type
[InlineData(570, GameIdentifierType.App, 570, GameIdentifierType.Sub)] // Same ID with different types
public void GetHashCode_ReturnsDifferentValueForUnequalGameIdentifiers(long id1, GameIdentifierType type1, long id2, GameIdentifierType type2) {
// Arrange
// Create two unequal game identifiers with the given ids and types
GameIdentifier gameIdentifier1 = new(id1, type1);
GameIdentifier gameIdentifier2 = new(id2, type2);

// Act and Assert
Assert.NotEqual(gameIdentifier1.GetHashCode(), gameIdentifier2.GetHashCode()); // The GetHashCode method should return different values for both game identifiers
}
}
Loading

0 comments on commit 690e796

Please sign in to comment.