HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/be.naniguide.com/tests/Unit/OrderFulfillment/OrderItemTypesLabelsTest.php
<?php

/**
 * OrderItemTypes::label() / icon() / tone() — single source of truth for type display.
 *
 * Guards against the regression where raw class names (e.g. "subscription.new",
 * or worse "App\\Model\\OrderItemNewSubscription") leak into the admin invoice list
 * because the blade falls through a missing trans key. See:
 *  - docs/automated/features/admin-subscriptions-invoices.md (BUG #1)
 *  - CLAUDE.md HARD RULE #2 (no fall-through on enum/state)
 */

use App\Library\OrderFulfillment\OrderItemTypes;
use Tests\TestCase;

uses(TestCase::class);

it('resolves a translated label for every known type', function (string $type) {
    $label = OrderItemTypes::label($type);

    expect($label)->toBeString()->not->toBe('');
    expect($label)->not->toContain('refactor/admin_invoices');
    expect($label)->not->toBe($type);
})->with(OrderItemTypes::all());

it('returns "—" for null/empty type', function () {
    expect(OrderItemTypes::label(null))->toBe('—');
    expect(OrderItemTypes::label(''))->toBe('—');
});

it('falls back to a humanised form for unknown types instead of leaking the code', function () {
    $unknown = 'mystery.payload';
    $label = OrderItemTypes::label($unknown);

    expect($label)->not->toBe($unknown);
    expect($label)->toContain('Mystery');
});

it('maps every known type to a non-empty material icon', function (string $type) {
    expect(OrderItemTypes::icon($type))->toBeString()->not->toBe('');
})->with(OrderItemTypes::all());

it('returns "receipt" icon as the safe fallback for unknown types', function () {
    expect(OrderItemTypes::icon(null))->toBe('receipt');
    expect(OrderItemTypes::icon('foo.bar'))->toBe('receipt');
});

it('maps every known type to a non-empty tone token', function (string $type) {
    expect(OrderItemTypes::tone($type))->toBeString()->not->toBe('');
})->with(OrderItemTypes::all());

it('returns "default" tone as the fallback', function () {
    expect(OrderItemTypes::tone(null))->toBe('default');
    expect(OrderItemTypes::tone('foo.bar'))->toBe('default');
});

/* ─────────── Legacy FQCN aliases — pre-schema-refactor data ─────────── */

it('label() resolves legacy FQCN OrderItem* class names to the modern label', function () {
    expect(OrderItemTypes::label('App\\Model\\OrderItemNewSubscription'))
        ->toBe(OrderItemTypes::label(OrderItemTypes::SUBSCRIPTION_NEW));

    expect(OrderItemTypes::label('App\\Model\\OrderItemRenewSubscription'))
        ->toBe(OrderItemTypes::label(OrderItemTypes::SUBSCRIPTION_RENEW));

    expect(OrderItemTypes::label('App\\Model\\OrderItemChangePlan'))
        ->toBe(OrderItemTypes::label(OrderItemTypes::SUBSCRIPTION_CHANGE_PLAN));

    expect(OrderItemTypes::label('App\\Model\\OrderItemSendingCreditsTopup'))
        ->toBe(OrderItemTypes::label(OrderItemTypes::CREDIT_SENDING_TOPUP));
});

it('icon() and tone() also normalise legacy FQCN before mapping', function () {
    expect(OrderItemTypes::icon('App\\Model\\OrderItemNewSubscription'))->toBe('person_add');
    expect(OrderItemTypes::icon('App\\Model\\OrderItemRenewSubscription'))->toBe('autorenew');
    expect(OrderItemTypes::tone('App\\Model\\OrderItemNewSubscription'))->toBe('teal');
    expect(OrderItemTypes::tone('App\\Model\\OrderItemRenewSubscription'))->toBe('blue');
});

it('label() never leaks "App\\Model\\" prefix even for unknown legacy FQCN', function () {
    $unknown = 'App\\Model\\OrderItemMysteryThing';
    $label = OrderItemTypes::label($unknown);

    // Falls through to humaniser — still must not contain the raw class path or the slashes.
    expect($label)->not->toContain('App\\')
        ->not->toContain('App\\Model')
        ->not->toBe($unknown);
});