fix: distinguish GPU model suffixes (Ti/Super/XT) and seed RTX 5060 series
RTX 5060 investigation: confirmed via pc-builder.io's own server-side
search (search_query=RTX 5060 against the full 6222-product GPU catalog,
0 results) that it simply isn't in pc-builder.io's catalog yet - not a
scraping bug, the source data doesn't have it. However, while checking
whether the other merchants had it in stock, found a real matching bug:
labelMatchesModelToken bug: extractModelToken("...RTX 5060 Ti...") only
returned "5060", identical to extractModelToken("...RTX 5060...") without
Ti. Every merchant lookup for either card matched on plain "5060" and
could silently return the *other* card's price (confirmed live: LDLC and
Grosbill returned the exact same product/price for both "RTX 5060" and
"RTX 5060 Ti" queries before this fix).
Fixed by:
- extractModelToken now appends a trailing suffix token (Ti, Super, XT,
XTX) when it immediately follows the model number, so "5060 Ti" and
"5060" are extracted as distinct tokens
- New labelMatchesModelToken() replaces the naive
label.includes(modelToken) check everywhere: a bare token ("5060") no
longer matches a label that actually has a suffix right after it
("5060 Ti"), while a suffixed token ("5060 Ti") only matches labels
carrying that exact suffix
- 9 new unit tests covering extraction and matching, including the
regression case (RTX 5060 must not match "RTX 5060 Ti" labels)
Verified fix live: LDLC/Grosbill now return correctly distinct prices for
"RTX 5060" (369.95/364.99) vs "RTX 5060 Ti" (489.95/329.99).
New manual_part_seeder_service.ts: since pc-builder.io's catalog lags
behind real product releases, this seeds a small manually-tracked list of
recent parts it doesn't carry yet (currently RTX 5060 8GB and 5060 Ti
16GB), resolving their price live from the already-supported merchants
rather than hardcoding a number that would go stale. `scrape:parts` now
runs this after the regular catalog scrape. Skips an entry rather than
inserting a guessed price if no merchant has it in stock.
Also fixes a real bug hit while testing the seeder: scraped_parts and
components.purchase_url were varchar(255), which truncates/rejects
Grosbill's long tracking-redirect URLs (500+ characters with encoded
analytics params) - both widened to TEXT via a new migration.
This commit is contained in:
1 parent
21d56a5da4
commit
54c5e37766
5 files changed
+225
-14
No files matched your search
@@ -0,0 +1,46 @@
|
||||
import { test } from '@japa/runner'
|
||||
import { extractModelToken, labelMatchesModelToken } from '#services/merchant_price_service'
|
||||
|
||||
test.group('extractModelToken', () => {
|
||||
test('extracts a bare model number', ({ assert }) => {
|
||||
assert.equal(extractModelToken('Samsung 970 Evo Plus 1 TB Solid State Drive'), '970')
|
||||
})
|
||||
|
||||
test('extracts an alphanumeric model number', ({ assert }) => {
|
||||
assert.equal(extractModelToken('AMD Ryzen 3 3200G 3.6 GHz Quad-Core Processor'), '3200G')
|
||||
})
|
||||
|
||||
test('appends a known suffix immediately following the model number', ({ assert }) => {
|
||||
assert.equal(extractModelToken('NVIDIA GeForce RTX 5060 Ti 16 GB Video Card'), '5060 Ti')
|
||||
assert.equal(extractModelToken('NVIDIA GeForce RTX 4070 Super 12 GB Video Card'), '4070 Super')
|
||||
})
|
||||
|
||||
test('does not append a suffix when the model number has none', ({ assert }) => {
|
||||
assert.equal(extractModelToken('NVIDIA GeForce RTX 5060 8 GB Video Card'), '5060')
|
||||
})
|
||||
|
||||
test('returns null when no model-like token is found', ({ assert }) => {
|
||||
assert.isNull(extractModelToken('Some Generic Product Without Any Model Number'))
|
||||
})
|
||||
})
|
||||
|
||||
test.group('labelMatchesModelToken', () => {
|
||||
test('a bare model token matches a label with no suffix', ({ assert }) => {
|
||||
assert.isTrue(labelMatchesModelToken('MSI VENTUS 2X OC NVIDIA GeForce RTX 5060 8G', '5060'))
|
||||
})
|
||||
|
||||
test('a bare model token does NOT match a label carrying a known suffix', ({ assert }) => {
|
||||
// Regression: RTX 5060 vs RTX 5060 Ti must never be conflated - they
|
||||
// are different, differently-priced cards.
|
||||
assert.isFalse(labelMatchesModelToken('PNY NVIDIA GeForce RTX 5060 Ti 8G OC', '5060'))
|
||||
})
|
||||
|
||||
test('a suffixed model token only matches labels with that exact suffix', ({ assert }) => {
|
||||
assert.isTrue(labelMatchesModelToken('PNY NVIDIA GeForce RTX 5060 Ti 8G OC', '5060 Ti'))
|
||||
assert.isFalse(labelMatchesModelToken('MSI VENTUS 2X OC NVIDIA GeForce RTX 5060 8G', '5060 Ti'))
|
||||
})
|
||||
|
||||
test('returns false when the token is not present at all', ({ assert }) => {
|
||||
assert.isFalse(labelMatchesModelToken('AMD Radeon RX 7800 XT', '5060'))
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user