OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

UnmatchedDeviceAssignTest.php

4 KB
<?php

declare(strict_types=1);

use OpenNIT\Controllers\AssetController;

/**
 * Deckt die Zuordnung eines unbekannten Geräts zu einem vorhandenen Asset ab.
 *
 * Der Weg besteht aus drei Teilen, die zusammenpassen müssen: ein Suchfeld, ein
 * Endpunkt dahinter und eine Auswahl, die als asset_id im Formular landet.
 * Fehlt ein Teil, bleibt das Feld ohne sichtbare Wirkung.
 */
return static function (): void {

    $template = static fn (): string => (string)file_get_contents(
        dirname(__DIR__) . '/templates/admin/assets/unmatched-devices.php'
    );

    // ----------------------------------------------------------------
    // Endpunkt
    // ----------------------------------------------------------------

    test('Der Suchendpunkt existiert und ist erreichbar registriert', function () {
        assertTrue(
            method_exists(AssetController::class, 'unmatchedDeviceAssetSearch'),
            'Die Aktion fehlt'
        );

        $app = (string)file_get_contents(dirname(__DIR__) . '/src/Core/Application.php');
        assertTrue(
            str_contains($app, "'/admin/inventory/unmatched-devices/asset-search'"),
            'Die Route fehlt'
        );
        // Vor der {id}-Route, damit "asset-search" nicht als ID gelesen wird.
        assertTrue(
            strpos($app, "'/admin/inventory/unmatched-devices/asset-search'")
            < strpos($app, "'/admin/inventory/unmatched-devices/{id}/assign'"),
            'Die Suchroute steht hinter der {id}-Route'
        );
    });

    test('Die Suche folgt dem Recht, das auch die Zuordnung verlangt', function () {
        // Ein Treffer, den man anschließend nicht beschreiben darf, wäre irreführend.
        $src = (string)file_get_contents(dirname(__DIR__) . '/src/Controllers/AssetController.php');
        $von = strpos($src, 'public function unmatchedDeviceAssetSearch');
        assertTrue($von !== false);
        $block = substr($src, $von, 2500);

        assertTrue(str_contains($block, "authorize('manage_assets')"), 'Keine Rechteprüfung');
        assertTrue(str_contains($block, "accessibleLocations('manage_assets')"), 'Kein Standort-Filter');
        assertTrue(str_contains($block, "status <> 'decommissioned'"), 'Ausgemusterte Assets sind nicht ausgeschlossen');
    });

    // ----------------------------------------------------------------
    // Oberfläche
    // ----------------------------------------------------------------

    test('Das Suchfeld ist mit dem Endpunkt verbunden', function () use ($template) {
        $tpl = $template();

        assertTrue(str_contains($tpl, "getElementById('assetSearch').addEventListener('input'"), 'Kein Listener am Suchfeld');
        assertTrue(str_contains($tpl, '/admin/inventory/unmatched-devices/asset-search?q='), 'Kein Aufruf des Endpunkts');
        assertTrue(str_contains($tpl, 'encodeURIComponent'), 'Der Suchbegriff wird nicht kodiert');
    });

    test('Ein Treffer wird als auswählbares asset_id angeboten', function () use ($template) {
        // Der Absende-Handler erwartet genau dieses Feld.
        $tpl = $template();

        assertTrue(str_contains($tpl, 'name="asset_id"'), 'Die Treffer bieten kein auswählbares Feld');
        assertTrue(str_contains($tpl, "querySelector('input[name=\"asset_id\"]:checked')"), 'Die Auswahl wird nicht gelesen');
    });

    test('Fremde Angaben werden vor der Ausgabe entschärft', function () use ($template) {
        // Asset-Namen stammen unter anderem aus Sync-Quellen.
        $tpl = $template();

        assertTrue(str_contains($tpl, 'function escapeHtml('), 'Keine Maskierung vorhanden');
        assertTrue(str_contains($tpl, 'escapeHtml(a.inventory_number'), 'Treffer werden unmaskiert eingesetzt');
    });

    test('Die Suche startet erst ab zwei Zeichen und entprellt', function () use ($template) {
        $tpl = $template();

        assertTrue(str_contains($tpl, 'begriff.length < 2'), 'Keine Mindestlänge');
        assertTrue(str_contains($tpl, 'clearTimeout(assetSearchTimer)'), 'Keine Entprellung');
    });
};