message)->toBe('Сбой для [PHONE] при импорте') ->and($out->message)->not->toContain('79161234567'); }); test('маскирует +7 и 8 форматы телефона', function () { $p = new PiiScrubbingProcessor; expect($p(piiTestRecord('a +79161234567 b'))->message)->toBe('a [PHONE] b') ->and($p(piiTestRecord('a 89161234567 b'))->message)->toBe('a [PHONE] b'); }); test('маскирует email в message → [EMAIL]', function () { $out = (new PiiScrubbingProcessor)(piiTestRecord('user ivan@example.ru вошёл')); expect($out->message)->toBe('user [EMAIL] вошёл'); }); test('маскирует телефон и email во вложенном context', function () { $out = (new PiiScrubbingProcessor)(piiTestRecord('msg', [ 'phone' => '79991234567', 'nested' => ['email' => 'a@b.ru', 'note' => 'без пдн'], ])); expect($out->context['phone'])->toBe('[PHONE]') ->and($out->context['nested']['email'])->toBe('[EMAIL]') ->and($out->context['nested']['note'])->toBe('без пдн'); }); test('не маскирует длинную цифровую строку (14 цифр) — нет ложного срабатывания', function () { $out = (new PiiScrubbingProcessor)(piiTestRecord('id 79161234567890 ok')); expect($out->message)->toBe('id 79161234567890 ok'); }); test('не-строковые значения context сохраняются как есть', function () { $out = (new PiiScrubbingProcessor)(piiTestRecord('msg', ['count' => 42, 'flag' => true, 'nil' => null])); expect($out->context['count'])->toBe(42) ->and($out->context['flag'])->toBe(true) ->and($out->context['nil'])->toBeNull(); });