Some checks are pending
QA Gate (P0/P1) / Test affected app (pull_request) Waiting to run
Faz 1 / adım 6 (analiz: /home/s/ss/plv2.md, bulgu p4legacy-03).
SORUN: Bu markalar ana gruplarını <a href> ile DEĞİL, satır attribute'uyla
veriyor:
Opel <tr class="tc-data-row" jsonurl="json-vin-main-group.action?catId=25
&mainGroupId=394…" caption="BODY SHELL AND PANELS" ident="394">
Hyundai <tr class="tc-data-row" url="vin-group.action?…&mainGroup=BO…">
<td>BO</td><td>BODY</td>
decodeVin yolu yalnız anchor tarayan parseP4NavigationCategories'i kullanıyordu
→ sayfa listeyi taşıdığı hâlde 0 kategori. Prod ölçümü (raw_data.categories):
Opel 177/181 (%97,8), Hyundai 12/12, Kia 6/6, Nissan 1/1 araç decode anında BOŞ.
(Kategori tablosu sonradan lazy-seed ile doluyor, ama decode kategorisiz
döndüğü için kullanıcı ilk açılışta boş görüyor ve prefetch self-seed'e zorlanıyor.)
Üç ayrı kusur vardı:
1. `parseFordGroupsFromHtml` bu satırları zaten anlıyor ama decode'dan hiç
çağrılmıyordu → kategori zincirine fallback olarak eklendi
(JSON ucu → tc-data-row tablosu → anchor taraması).
2. Volvo için konmuş `vin-group.action && !group1=` guard'ı Hyundai/Kia'nın
AYNI ucu `mainGroup=` anahtarıyla kullanan gerçek ana gruplarını da eliyordu
→ artık `group1=` veya `mainGroup=` taşıyan satırlar korunuyor.
3. Satır attribute'ları HTML-escaped (`&`), bu yüzden `[?&]mainGroup=`
kontrolü hiç tutmuyordu → URL artık ayrıştırma anında entity-decode ediliyor
(saklanan linkPath de böylece temiz).
Test: yeni `pl24-p4-groups.spec.ts` + 2026-09-16 canlı yakalamalarından kırpılmış
fixture'lar (`__fixtures__/p4_{opel,hyundai,ford,nissan}.html`). Opel 31 ana grup
("BODY SHELL AND PANELS"…), Hyundai 6 ("BODY"…), anchor-only parser'ın bu
sayfalarda hâlâ 0 döndüğü (fallback'in gerekçesi), Ford sharedCatCode scope
satırlarının bozulmadığı ve Nissan model-seçim satırlarının elendiği kilitlendi.
213 test geçti; tsc + biome temiz.
NOT: db_hit kısa devresi yüzünden mevcut araçlar kendiliğinden düzelmez; kazanç
yeni decode'larda. Toplu yeniden decode Faz 2'de.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
71 lines
3.1 KiB
TypeScript
71 lines
3.1 KiB
TypeScript
import { readFileSync } from "node:fs";
|
||
import { join } from "node:path";
|
||
import { describe, expect, it } from "vitest";
|
||
import { PL24FordLegacyService } from "./pl24-ford-legacy.service";
|
||
|
||
/**
|
||
* Opel / Hyundai / Kia "0 kategori" regresyon kilidi (plv2.md, bulgu p4legacy-03).
|
||
*
|
||
* Bu markalar ana gruplarını <a href> DEĞİL, `<tr class="tc-data-row"
|
||
* url=…|jsonurl=…>` satır attribute'unda taşıyor. Decode yolu yalnız anchor
|
||
* tarayan parser'ı kullandığı için prod'da Opel 169/173, Hyundai 11/11, Kia 5/5
|
||
* araç SIFIR kategoriyle kaydedilmişti — sayfa listeyi taşıdığı hâlde.
|
||
*
|
||
* Fixture'lar 2026-09-16 canlı keşfinden (plv2-artefakt/), yalnız ana grup
|
||
* tablosuna kırpılmış hâlleri.
|
||
*/
|
||
|
||
const fixture = (name: string) =>
|
||
readFileSync(join(__dirname, "__fixtures__", `${name}.html`), "utf-8");
|
||
|
||
// parseFordGroupsFromHtml saf bir metin işleyicisi: bağımlılıklar kullanılmıyor.
|
||
const svc = new PL24FordLegacyService(
|
||
{} as never, // authService
|
||
{ get: (_k: string, d?: unknown) => d } as never, // configService
|
||
{} as never, // redis
|
||
{} as never, // storage
|
||
) as unknown as {
|
||
parseFordGroupsFromHtml(
|
||
html: string,
|
||
serviceName: string,
|
||
familyId: string,
|
||
): Array<{ code: string; nameEn: string; linkPath?: string }>;
|
||
parseP4NavigationCategories(html: string): Array<{ nameEn: string }>;
|
||
};
|
||
|
||
describe("P4 ana grup tablosu — Opel/Hyundai (0 kategori regresyonu)", () => {
|
||
it("Opel: jsonurl satırlarından 31 ana grubu çıkarır", () => {
|
||
const groups = svc.parseFordGroupsFromHtml(fixture("p4_opel"), "opel_parts", "");
|
||
expect(groups.length).toBe(31);
|
||
expect(groups[0].nameEn).toBe("BODY SHELL AND PANELS");
|
||
expect(groups[0].code).toContain("json-vin-main-group.action");
|
||
expect(groups[0].code).toContain("mainGroupId=394");
|
||
// Adların hepsi gerçek metin olmalı (kod artığı değil)
|
||
expect(groups.every((g) => /[A-Za-z]{3,}/.test(g.nameEn))).toBe(true);
|
||
});
|
||
|
||
it("Hyundai: mainGroup= anahtarlı vin-group satırları artık elenmez", () => {
|
||
const groups = svc.parseFordGroupsFromHtml(fixture("p4_hyundai"), "hyundai_parts", "");
|
||
expect(groups.length).toBe(6);
|
||
const names = groups.map((g) => g.nameEn);
|
||
expect(names).toContain("BODY");
|
||
expect(groups[0].code).toContain("mainGroup=BO");
|
||
});
|
||
|
||
it("anchor-only parser bu sayfalarda hâlâ boş döner (fallback'in gerekçesi)", () => {
|
||
expect(svc.parseP4NavigationCategories(fixture("p4_opel")).length).toBe(0);
|
||
expect(svc.parseP4NavigationCategories(fixture("p4_hyundai")).length).toBe(0);
|
||
});
|
||
|
||
it("Ford: scope satırları (sharedCatCode) bozulmadan okunur", () => {
|
||
const groups = svc.parseFordGroupsFromHtml(fixture("p4_ford"), "fordp_parts", "");
|
||
expect(groups.length).toBeGreaterThanOrEqual(6);
|
||
expect(groups.some((g) => g.code.includes("sharedCatCode=ZE"))).toBe(true);
|
||
});
|
||
|
||
it("Nissan: model seçim satırları ana grup sayılmaz (vehicle.action elenir)", () => {
|
||
const groups = svc.parseFordGroupsFromHtml(fixture("p4_nissan"), "nissan_parts", "");
|
||
expect(groups.every((g) => !g.code.includes("vehicle.action"))).toBe(true);
|
||
});
|
||
});
|