ReviewOS

also looking at this

chris/predicthq

feat: scrape Transfermarkt club valuations

#2
Merged chris wants to merge codex/transfermarkt-dom into main
5 files +131 -57
tests/unit/mismatch.test.tsmodified+31-1
Changes to tests/unit/mismatch.test.ts
@@ -1,7 +1,7 @@
11import { describe, expect, it } from 'bun:test'
22import { assessMismatch, type TeamFundamentals } from '../../app/Services/fundamentals/mismatch'
33import { injurySeverity } from '../../app/Services/fundamentals/severity'
4import { parseMarketValue } from '../../app/Services/fundamentals/transfermarkt'
4import { parseMarketValue, parseTransfermarktClubs } from '../../app/Services/fundamentals/transfermarkt'
55
66/**
77 * The mismatch read is the only input in this system that can disagree
@@ -169,3 +169,33 @@ describe('parseMarketValue', () => {
169169 expect(parseMarketValue(null)).toBe(0)
170170 })
171171})
172
173describe('parseTransfermarktClubs', () => {
174 it('keeps every club fact attached to its Transfermarkt DOM row', () => {
175 const clubs = parseTransfermarktClubs(`
176 <table class="items">
177 <tbody>
178 <tr><td colspan="7">Clubs - Premier League</td></tr>
179 <tr class="odd">
180 <td class="zentriert"><a href="/brighton/startseite/verein/123"><img alt="Brighton"></a></td>
181 <td class="hauptlink no-border-links"><a title="Brighton &amp; Hove Albion" href="/brighton/startseite/verein/123/saison_id/2026">Brighton &amp; Hove Albion</a></td>
182 <td class="zentriert">33</td><td class="zentriert">26.6</td><td class="zentriert">21</td>
183 <td class="rechts">€16.73m</td><td class="rechts hauptlink"><a href="/brighton/marktwert/verein/123">€552.00m</a></td>
184 </tr>
185 <tr class="even">
186 <td class="zentriert"><a href="/arsenal/startseite/verein/11"><img alt="Arsenal"></a></td>
187 <td class="hauptlink no-border-links"><a title="Arsenal FC" href="/arsenal/startseite/verein/11/saison_id/2026">Arsenal FC</a></td>
188 <td class="zentriert">24</td><td class="zentriert">26.3</td><td class="zentriert">17</td>
189 <td class="rechts">€51.21m</td><td class="rechts hauptlink"><a href="/arsenal/marktwert/verein/11">€1.23bn</a></td>
190 </tr>
191 </tbody>
192 </table>
193 <table class="items"><tbody><tr><td class="hauptlink"><a href="/player/profil/spieler/9">Player</a></td></tr></tbody></table>
194 `)
195
196 expect(clubs).toEqual([
197 { externalId: '123', name: 'Brighton & Hove Albion', squadSize: 33, averageAgeYears: 26.6, marketValueEur: 552_000_000 },
198 { externalId: '11', name: 'Arsenal FC', squadSize: 24, averageAgeYears: 26.3, marketValueEur: 1_230_000_000 },
199 ])
200 })
201})