158 lines
5.6 KiB
PHP
158 lines
5.6 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
|
||
namespace Cf7stg\Tests;
|
||
|
||
use Cf7stg\Classifier;
|
||
use PHPUnit\Framework\TestCase;
|
||
|
||
final class ClassifierTest extends TestCase
|
||
{
|
||
public function test_real_client_inquiry_is_green(): void
|
||
{
|
||
$fields = [
|
||
'your-name' => 'Анна Петровна',
|
||
'your-tel' => '+7 903 123-45-67',
|
||
'your-email' => 'anna@mail.ru',
|
||
'your-message' => 'Нужна сиделка для бабушки после инсульта, пожалуйста перезвоните.',
|
||
];
|
||
$r = Classifier::classify($fields, ['reason' => 'Akismet']);
|
||
self::assertSame('client', $r['label']);
|
||
self::assertGreaterThanOrEqual(3, $r['score']);
|
||
}
|
||
|
||
public function test_seo_spam_with_url_is_red(): void
|
||
{
|
||
$fields = [
|
||
'your-name' => 'Melissa Johnson',
|
||
'your-email' => 'promo@example.com',
|
||
'your-message' => 'Hi, we boost SEO positions, visit http://cheap-seo.net',
|
||
];
|
||
$r = Classifier::classify($fields, ['reason' => 'Akismet']);
|
||
self::assertSame('spam', $r['label']);
|
||
self::assertLessThanOrEqual(-2, $r['score']);
|
||
}
|
||
|
||
public function test_honeypot_forces_spam_even_with_phone(): void
|
||
{
|
||
$fields = [
|
||
'your-name' => 'Анна',
|
||
'your-tel' => '+79031234567',
|
||
'your-message' => 'сиделка для мамы',
|
||
];
|
||
$r = Classifier::classify($fields, ['reason' => 'Honeypot']);
|
||
self::assertSame('spam', $r['label']);
|
||
}
|
||
|
||
public function test_empty_fields_are_unclear(): void
|
||
{
|
||
$fields = [
|
||
'your-email' => 'a@b.com',
|
||
];
|
||
$r = Classifier::classify($fields, ['reason' => 'CF7 rules']);
|
||
self::assertSame('unclear', $r['label']);
|
||
}
|
||
|
||
public function test_multiple_keywords_capped_at_minus_six(): void
|
||
{
|
||
$fields = [
|
||
'your-message' => 'SEO, SEO, SEO, backlinks, crypto, casino, займ, bitcoin',
|
||
];
|
||
$r = Classifier::classify($fields, ['reason' => 'Akismet']);
|
||
// 8 hits × -2 would be -16; cap is -6
|
||
self::assertGreaterThanOrEqual(-10, $r['score']); // keyword part >= -6, plus -3 for URL? none here
|
||
}
|
||
|
||
public function test_ru_domain_email_adds_one(): void
|
||
{
|
||
$fields = [
|
||
'your-name' => 'Иван',
|
||
'your-email' => 'ivan@yandex.ru',
|
||
'your-message' => 'Здравствуйте, интересует услуга сиделки',
|
||
];
|
||
$r = Classifier::classify($fields, ['reason' => 'Akismet']);
|
||
$hasRuMail = false;
|
||
foreach ($r['reasons'] as $reason) {
|
||
if (strpos($reason['text'], 'ру-домен') !== false) {
|
||
$hasRuMail = true;
|
||
}
|
||
}
|
||
self::assertTrue($hasRuMail);
|
||
}
|
||
|
||
public function test_reasons_list_contains_sign_and_weight(): void
|
||
{
|
||
$fields = [
|
||
'your-tel' => '+79031234567',
|
||
];
|
||
$r = Classifier::classify($fields, ['reason' => 'Akismet']);
|
||
self::assertNotEmpty($r['reasons']);
|
||
self::assertArrayHasKey('sign', $r['reasons'][0]);
|
||
self::assertArrayHasKey('weight', $r['reasons'][0]);
|
||
self::assertArrayHasKey('text', $r['reasons'][0]);
|
||
}
|
||
|
||
public function test_latin_only_name_penalty(): void
|
||
{
|
||
$fields = [
|
||
'your-name' => 'John Smith',
|
||
'your-message' => 'please help me with website ranking',
|
||
];
|
||
$r = Classifier::classify($fields, ['reason' => 'Akismet']);
|
||
$hasLatinPenalty = false;
|
||
foreach ($r['reasons'] as $reason) {
|
||
if ($reason['sign'] === '-' && strpos($reason['text'], 'латиница') !== false) {
|
||
$hasLatinPenalty = true;
|
||
}
|
||
}
|
||
self::assertTrue($hasLatinPenalty);
|
||
}
|
||
|
||
public function test_url_in_any_field_triggers_minus_three(): void
|
||
{
|
||
$fields = [
|
||
'your-name' => 'Ольга',
|
||
'your-message' => 'посмотрите https://мойсайт.рф',
|
||
];
|
||
$r = Classifier::classify($fields, ['reason' => 'Akismet']);
|
||
$hasUrl = false;
|
||
foreach ($r['reasons'] as $reason) {
|
||
if (strpos($reason['text'], 'URL') !== false) {
|
||
$hasUrl = true;
|
||
self::assertSame('-', $reason['sign']);
|
||
self::assertSame(3, $reason['weight']);
|
||
}
|
||
}
|
||
self::assertTrue($hasUrl);
|
||
}
|
||
|
||
public function test_thresholds_client_edge(): void
|
||
{
|
||
// Score exactly 3 → client
|
||
$fields = ['your-tel' => '+79031234567'];
|
||
$r = Classifier::classify($fields, ['reason' => 'Akismet']);
|
||
self::assertSame(3, $r['score']);
|
||
self::assertSame('client', $r['label']);
|
||
}
|
||
|
||
public function test_thresholds_unclear_between_neg_one_and_two(): void
|
||
{
|
||
$fields = ['your-name' => 'Олег', 'your-message' => 'короткий'];
|
||
$r = Classifier::classify($fields, ['reason' => 'Akismet']);
|
||
self::assertGreaterThan(-2, $r['score']);
|
||
self::assertLessThan(3, $r['score']);
|
||
self::assertSame('unclear', $r['label']);
|
||
}
|
||
|
||
public function test_keyword_matching_case_insensitive(): void
|
||
{
|
||
$fields = ['your-message' => 'Продаём ВИАГРА с доставкой'];
|
||
$r = Classifier::classify($fields, ['reason' => 'Akismet']);
|
||
$matched = false;
|
||
foreach ($r['reasons'] as $reason) {
|
||
if (strpos($reason['text'], 'виагра') !== false) $matched = true;
|
||
}
|
||
self::assertTrue($matched);
|
||
}
|
||
}
|