Skip to content

feat: automated daily leetcode challenges integration#421

Draft
Dejmenek wants to merge 11 commits into
masterfrom
416-feat-automated-daily-leetcode-challenges-integration
Draft

feat: automated daily leetcode challenges integration#421
Dejmenek wants to merge 11 commits into
masterfrom
416-feat-automated-daily-leetcode-challenges-integration

Conversation

@Dejmenek

@Dejmenek Dejmenek commented May 5, 2026

Copy link
Copy Markdown
Contributor

Description

Automates daily addition of new LeetCode coding challenges into the platform.

Related Issue

Closes #416

Type of Change

  • Bug fix
  • New feature
  • Refactor (no functional change)
  • Tests
  • Documentation
  • CI/CD / configuration
  • Other:

Implementation Details

  • Added IDailyChallengeFetchService interface with a single FetchDailyChallenge() method. Future platforms (Codewars, HackerRank, etc.) can be added without touching DailyChallengeJob.
  • Added LeetCodeDailyChallengeService which calls LeetCode API to get current challenge, maps LeetCode difficulty (Easy/Medium/Hard) to the existing Level enum and XP values (5/10/15). Skips premium problems. Detects SQL and C# challenges. Strips HTML from the problem content and extracts the first sentence for Description.
  • DailyChallengeJob is a background service which runs once a day and calls every registered IDailyChallengeFetchService to get daily challenges. Later uses ChallengeService to save them to the database. Scoped services are resolved safely by using IServiceScopeFactory.
  • ChallengeService.AddChallenge - checks for an existing record by ExternalId before inserting to prevent duplicates. Returns a BaseResponse with success/fail status.
  • Added new GetDailyChallenge graphql query to ChallengePlatformConstants.
  • Added LeetCodeDailyResponse strongly-typed models for GetDailyChallenge query result.
  • Added LeetCodeDailyChallengeServiceTests.FetchDailyChallenge_ShouldReturnValidChallenge integration test that hits real LeetCode GraphQL API and asserts that the returned Challenge has a non-empty ExternalId, Name, and Description, the correct Platform, ReleaseDate, a valid Level, the correct XP value, and a valid Category.
  • ChallengeServiceTests was extended with an integration test asserting that calling AddChallenge twice with the ExternalId returns a failure response on the second call, verifying the duplicate-prevention logic.

Testing Performed

  • Ran existing unit tests (dotnet test TCSA.V2026.UnitTests/)
  • Ran existing integration tests (dotnet test TCSA.2026.IntegrationTests/)
  • Ran existing end-to-end tests (dotnet test TCSA.2026.EndToEndTests/)
  • Added new tests covering the change
  • Manually verified in the browser

Checklist

  • My code follows the existing code style and conventions
  • I have read the related issue and my implementation matches the requirements
  • No sensitive data (credentials, secrets) committed
  • All new and existing tests pass

Additional Context

To test it locally, you can: change the value of PeriodicTimer, run the app, wait for the background job to execute, then go to the challenges page.

Dejmenek added 10 commits May 5, 2026 17:49
Added AddChallenge method to ChallengeService for inserting new challenges into the database. The method checks for duplicate ExternalId values, returns standardized BaseResponse objects, and logs errors using ILogger. Updated IChallengeService interface and constructor to support these changes.
Introduced new record types in the TCSA.V2026.Data.Models.Responses namespace to represent LeetCode daily challenge data. Added LeetCodeDailyResult, LeetCodeDailyQuestion, LeetCodeTopicTag, and LeetCodeDailyProblem records to provide structured modeling of daily challenge questions, their metadata, and associated topic tags. This enables better handling and integration of LeetCode daily challenge information within the application.
Added the GetDailyChallenge constant to ChallengePlatformConstants. This constant holds a GraphQL query to fetch the active daily coding challenge question, including its date, title, slug, difficulty, paid status, content, and topic tags.
Introduce DailyChallengeJob in TCSA.V2026.Services.Challenges. This BackgroundService uses dependency injection to fetch daily challenges from all IDailyChallengeFetchService implementations and adds them to IChallengeService every 24 hours using a PeriodicTimer.
Introduce IDailyChallengeFetchService interface and implement it with LeetCodeDailyChallengeService. The service fetches the daily challenge from LeetCode's GraphQL API, maps the response to the local Challenge model, and handles paid-only problems. Includes logic for difficulty mapping, XP assignment, and description extraction. Adds error logging and uses dependency injection for HttpClient and logger.
Registered LeetCodeDailyChallengeService as IDailyChallengeFetchService (scoped) and added DailyChallengeJob as a hosted service. These changes enable background processing and fetching of daily challenges, supporting new daily challenge functionality.
Added LeetCodeDailyChallengeServiceTests to verify the behavior of LeetCodeDailyChallengeService. The tests set up HTTP client factory and logger, and include a test to ensure the fetched daily challenge has valid properties, correct platform, release date, level, experience points, and category. This ensures the service correctly retrieves and parses daily challenges from LeetCode.
Cleaned up ChallengeService.cs, CodeWarsService.cs, and DailyChallengeJob.cs by removing unnecessary or unused using statements. This improves code readability and maintainability.
Updated ChallengeServiceTests to pass a NullLogger<ChallengeService> instance to ChallengeService during setup. Added the necessary using directive for Microsoft.Extensions.Logging.Abstractions to support this change. This ensures the service can accept a logger dependency in tests.
Added AddChallenge_ShouldNotAddDuplicate integration test to ChallengeServiceTests. This test ensures that adding a Challenge with a duplicate ExternalId fails with the correct message and does not create multiple entries in the database.
@Dejmenek Dejmenek linked an issue May 5, 2026 that may be closed by this pull request
@Dejmenek
Dejmenek marked this pull request as draft May 5, 2026 20:01
@Dejmenek
Dejmenek marked this pull request as ready for review May 6, 2026 12:27
@Dejmenek
Dejmenek requested a review from TheCSharpAcademy May 6, 2026 12:27
Comment thread TCSA.2026.IntegrationTests/LeetCodeDailyChallengeServiceTests.cs Outdated
Refactored LeetCodeDailyChallengeServiceTests to use Moq and a custom MockHttpMessageHandler, removing dependencies on real HTTP calls and service containers. Added focused test cases for easy, medium, hard, paid-only, and API failure scenarios. Introduced helper methods for payload generation and service creation. Removed the old generic test. Tests are now deterministic, isolated, and do not rely on external services or the current date. Added MockHttpMessageHandler.cs to support HTTP response mocking.
@Dejmenek
Dejmenek requested a review from TheCSharpAcademy May 18, 2026 19:18
@TheCSharpAcademy TheCSharpAcademy self-assigned this Jul 4, 2026
@Dejmenek
Dejmenek marked this pull request as draft July 5, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: automated daily LeetCode challenges integration

2 participants