Skip to content

Step 1: extract RuTrackerParser interface + TDD on real fixtures - #58

Closed
andrikeev wants to merge 1 commit into
masterfrom
claude/wizardly-gates-netx2r
Closed

andrikeev wants to merge 1 commit into
masterfrom
claude/wizardly-gates-netx2r

Conversation

@andrikeev

Copy link
Copy Markdown
Owner

Step 1 of decoupling parsing from app releases

Goal of the whole effort: be able to change rutracker parsing rules without shipping a new release, by eventually swapping in a config-driven parser. This PR builds the seam that makes that swap a one-line change, and pins current behaviour with tests on real pages.

What this PR does

  • New RuTrackerParser interface — a pure String html → DTO / Boolean contract, no network, no IO. It's the single place that holds all markup/text knowledge.
  • RuTrackerHtmlParser (ksoup) implements it, keeping the focused Parse*UseCase objects as the internal building blocks it delegates to (ParseTopicPageUseCase, ParseCommentsPageUseCase, ParseTorrentUseCase, ParsePostUseCase, ParseTorrentStatusUseCase).
  • Use cases become "fetch + delegate": the page-parsing use cases (search, category, forum, topic, comments, torrent, profile, current-user, favorites) and the page-state checks now call the parser instead of parsing inline. Parsing logic that was inlined in Get*UseCase / Utils moved into the parser.
  • RuTrackerApiFactory constructs the parser and injects it — this is the line Step 3 will swap.
  • Public NetworkApi contract is unchanged → blast radius stays inside :core:network:rutracker.

Tests (TDD on real HTML)

Characterization tests run against real saved rutracker pages in src/test/resources/fixtures/ — :core:network:rutracker:test is green (9/9). Covered: parseForum, parseCategoryPage, parseTorrent, parseTopicPage, parseCommentsPage (incl. quote/spoiler/image post content), parseProfile, and the topic-exists / forum-exists / is-authorized / is-torrent-topic states.

Known gap — authenticated fixtures needed

The search / favorites / main_authorized captures came back as login stubs (the session cookie wasn't authenticated — no logged-in-username anywhere), so these parsers aren't test-covered yet:

  • parseSearchPage, parseFavorites (+ page count), parseCurrentUserId, isAuthorized == true
  • the authenticated topic branch (#tor-status-resp status + #tor-size-humn size)

The interface methods exist and are implemented; tests will be added once authenticated fixtures are re-captured. The auth/login/form-token/captcha/action-result callers (WithFormTokenUseCase, LoginUseCase, add/remove favorite, add comment) are also still inline — they'll be routed through the parser in a follow-up increment.

Next

  • Step 2: design the versioned parsing config and a config-driven RuTrackerParser (also TDD against these same fixtures).
  • Step 3: swap the implementation in RuTrackerApiFactory.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EPxhiZbmURTJvhRzAHcpGu


Generated by Claude Code

Introduce RuTrackerParser — a pure (html -> DTO) seam with no network —
and its ksoup-backed RuTrackerHtmlParser implementation, which keeps the
focused Parse*UseCase objects as internal building blocks it delegates to.

The page-parsing use cases (search, category, forum, topic, comments,
torrent, profile, favorites) and the page-state checks now go through the
parser instead of parsing inline, so the whole parsing layer sits behind
one swappable interface. The public NetworkApi contract is unchanged.

Add characterization tests over real rutracker HTML fixtures for the
guest-viewable parsers (forum, category, topic, comments, profile, plus
the not-found / unauthorized states).

Step 1 of decoupling parsing rules from app releases: a config-driven
RuTrackerParser can later be swapped in via RuTrackerApiFactory.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EPxhiZbmURTJvhRzAHcpGu
@andrikeev andrikeev closed this Oct 1, 2026
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.

2 participants