import { describe, expect, it } from "vitest"; import { isUsableParse, isUsableRenaultParse, parseRenaultHeader, parseVinpinModal, } from "./vinpin.parser"; const SAMPLE = "MVS, найденные по vin NM435600006H43436 6J - TIPO - EGEA (2015-2021) 356G37001162 - 3V HIGH PLUS 1.6 120CV D5 CM E6 GS TR Двигатель: 8165300 Автомобиль: 279476 Prod. date: 2/8/2017 Vin: NM435600006H43436"; describe("parseVinpinModal", () => { it("parses the real ePER modal sample (TIPO-EGEA / 356G37001162 / 2017)", () => { const p = parseVinpinModal(SAMPLE); expect(p.model).toBe("TIPO-EGEA"); expect(p.sincom).toBe("356G37001162"); expect(p.modelYear).toBe("2017"); // from Prod. date, not the (2015-2021) range expect(p.engine).toBe("8165300"); expect(p.trim).toContain("HIGH PLUS"); expect(isUsableParse(p)).toBe(true); }); it("does not mistake the VIN or short engine number for a SINCOM code", () => { const p = parseVinpinModal(SAMPLE); expect(p.sincom).not.toContain("NM4356"); expect(p.sincom).not.toBe("8165300"); }); it("falls back to the year-range start when no production date is present", () => { const p = parseVinpinModal("9F - LINEA (2007-2017) 323A11005000 - 1.3 MJET"); expect(p.model).toBe("LINEA"); expect(p.sincom).toBe("323A11005000"); expect(p.modelYear).toBe("2007"); }); it("returns all-null for empty/garbage input and reports unusable", () => { const p = parseVinpinModal(""); expect(p.model).toBeNull(); expect(p.sincom).toBeNull(); expect(isUsableParse(p)).toBe(false); expect(isUsableParse(parseVinpinModal(null))).toBe(false); }); it("rejects a stale-breadcrumb model with no SINCOM (vehicle-not-found false positive)", () => { // Real garbled OCR of a failed NM4131 decode: the "не найден" alert is // mangled ("He HaaeHs") so it slips the not-found check, and the screen // still shows the operator's last catalog ("FIAT » TIPO - EGEA"). A model // token is present but there is NO SINCOM → must be treated as unusable so // it is not false-mapped onto the ancient "TIPO 1987-1993" catalog. const p = parseVinpinModal( "Fiat Dealer Spare Parts FIAT TIPO - EGBA 500 HYBRID TIPO-EGEA MCA (2020) DOBLO FREEMONT LINEA IDEA To yKasaHHeIM N3paMETpaM 3BTOMOBHMN He HaaeHs", ); expect(p.model).not.toBeNull(); // breadcrumb model still extracted… expect(p.sincom).toBeNull(); // …but no SINCOM expect(isUsableParse(p)).toBe(false); // → not a real decode }); }); describe("parseRenaultHeader", () => { it("parses an Rpartstore RENAULT header (model + brand)", () => { const p = parseRenaultHeader("RENAULT KADJAR (RFE) Şasi: VF1RFE00653633190"); expect(p.model).toBe("KADJAR"); expect(p.brand).toBe("RENAULT"); expect(isUsableRenaultParse(p)).toBe(true); }); it("reads DACIA as the brand when the header carries it", () => { const p = parseRenaultHeader("DACIA DUSTER (HSA) Şasi: VF1HJD40865644941"); expect(p.model).toBe("DUSTER"); expect(p.brand).toBe("DACIA"); }); it("extracts the base model and ignores the generation numeral (CLIO IV)", () => { const p = parseRenaultHeader("RENAULT CLIO IV (R0G) Şasi: VF15R0G0H49335605"); expect(p.model).toBe("CLIO"); expect(p.brand).toBe("RENAULT"); }); it("handles a Dialogys header with no explicit brand (defaults RENAULT)", () => { const p = parseRenaultHeader("Clio II (X65), 1.5 dCi"); expect(p.model).toBe("CLIO"); expect(p.brand).toBe("RENAULT"); }); it("captures a model year when the header carries one", () => { const p = parseRenaultHeader("RENAULT LATITUDE (2011-2015)"); expect(p.model).toBe("LATITUDE"); expect(p.modelYear).toBe("2011"); }); it("does NOT mis-grab the status-bar license-expiry date as the model year", () => { // The full-frame OCR fallback sweeps in the Rpartstore/Dialogys status bar, // whose license EXPIRY date ("…14.07.2026") used to be read as the model year. const p = parseRenaultHeader("RENAULT KADJAR (RFE) Şasi: VF1RFE00653633190 Lisans: 14.07.2026"); expect(p.model).toBe("KADJAR"); expect(p.modelYear).toBeNull(); // NOT "2026" from the expiry date }); it("still prefers a genuine generation range even when an expiry date is present", () => { const p = parseRenaultHeader("RENAULT LATITUDE (2011-2015) Lisans: 14.07.2026"); expect(p.modelYear).toBe("2011"); // the (2011-2015) range wins over the date }); it("returns no model / unusable for headers without a known token", () => { const p = parseRenaultHeader("İlişikli araç bulunamadı"); expect(p.model).toBeNull(); expect(isUsableRenaultParse(p)).toBe(false); expect(isUsableRenaultParse(parseRenaultHeader(""))).toBe(false); }); });