setAccessible(true); return $reflection->invoke($object, ...$args); } function makeProducer(string $name, string $status = DbStatusFieldEnum::active): Producer { return Producer::create(['name' => $name, 'status' => $status, 'canSee' => 1]); } test('a normalizálás összevonja a kis/nagybetű, szóköz és szeparátor eltéréseket', function () { expect(NameNormalizer::normalize('Danone'))->toBe('DANONE') ->and(NameNormalizer::normalize('Danone '))->toBe('DANONE') ->and(NameNormalizer::normalize(' danone '))->toBe('DANONE') ->and(NameNormalizer::normalize('Alba-Gel Kft'))->toBe('ALBA-GEL KFT') ->and(NameNormalizer::normalize('Tej/Sajt'))->toBe('TEJ SAJT') ->and(NameNormalizer::normalize('Tej_Sajt'))->toBe('TEJ SAJT') ->and(NameNormalizer::normalize(null))->toBe(''); }); test('a matches() üres nevet nem tekint egyezésnek', function () { expect(NameNormalizer::matches('Danone', 'danone '))->toBeTrue() ->and(NameNormalizer::matches('', ''))->toBeFalse() ->and(NameNormalizer::matches(null, 'Danone'))->toBeFalse(); }); test('a legacy import megtalálja a meglévő gyártót eltérő írásmód esetén is', function () { $existing = makeProducer('Danone'); $service = app(PriceListService::class); callPrivate($service, 'loadProducers', 'name'); // Ezek korábban mind ÚJ gyártót hoztak létre volna - így keletkezett 70 duplikátum. foreach (['Danone ', ' danone', 'DANONE', 'Danone '] as $variant) { $found = callPrivate($service, 'getProducerByName', $variant); expect($found)->not->toBeFalse() ->and($found['id'])->toBe($existing->id); } }); test('a legacy import változatlanul hagyja a valóban új gyártót', function () { makeProducer('Danone'); $service = app(PriceListService::class); callPrivate($service, 'loadProducers', 'name'); expect(callPrivate($service, 'getProducerByName', 'Bonduelle'))->toBeFalse() ->and(callPrivate($service, 'getProducerByName', ' '))->toBeFalse(); }); test('a karakterre pontos találat elsőbbséget élvez', function () { $old = makeProducer('Voyagex '); $new = makeProducer('Voyagex'); $service = app(PriceListService::class); callPrivate($service, 'loadProducers', 'name'); // Ha a fájlban pontosan az egyik rekord neve szerepel, azt kell visszaadni - // a normalizált egyeztetés csak tartalék útvonal. expect(callPrivate($service, 'getProducerByName', 'Voyagex')['id'])->toBe($new->id) ->and(callPrivate($service, 'getProducerByName', 'Voyagex ')['id'])->toBe($old->id); }); test('pontos találat híján duplikátumból a legrégebbi rekordot adja vissza', function () { // Ez a takarítás előtti adatállapot: a termékek túlnyomó része a régi rekordra // mutat, tehát az a kanonikus. Korábban a feloldás a LEGÚJABBAT választotta. $old = makeProducer('Voyagex '); $new = makeProducer('Voyagex'); $service = app(PriceListService::class); callPrivate($service, 'loadProducers', 'name'); // Egyik rekord nevével sem egyezik karakterre $found = callPrivate($service, 'getProducerByName', 'VOYAGEX'); expect($found['id'])->toBe($old->id) ->and($found['id'])->not->toBe($new->id); }); test('az új gyártó neve körülvágva kerül mentésre', function () { $service = app(PriceListService::class); $id = callPrivate($service, 'addNewProducer', ['name' => ' Vadonatúj Gyártó ']); expect(Producer::find($id)->name)->toBe('Vadonatúj Gyártó'); }); test('az archivált gyártó kimarad az árlista feldolgozó feloldásából', function () { $active = makeProducer('Danone'); $merged = makeProducer('Danone ', DbStatusFieldEnum::archive); $lookup = callPrivate(app(PricelistFileProcessService::class), 'getProducerLookupMap'); // Enélkül a beolvasztott rekord visszakerülne a feloldásba, és a takarítás // hatástalan maradna. expect($lookup['DANONE'] ?? null)->toBe($active->id) ->and(in_array($merged->id, $lookup, true))->toBeFalse(); });