---
title: "Testovanie — Passkeys for Laravel | Roundly"
description: "Zaznamenajte a overte ceremónie cez Passkeys::fake(), alebo spúšťajte skutočné ceremónie end-to-end so softvérovým VirtualAuthenticator."
url: https://roundly-consulting.com/sk/open-source/navody/passkeys-for-laravel/testovanie
language: sk
---

[Všetky balíky](https://roundly-consulting.com/sk/open-source.md)

[Passkeys for Laravel](https://roundly-consulting.com/sk/open-source/navody/passkeys-for-laravel.md)

# Testovanie

Passkeys::fake() nahradí relying party triedou PasskeysFake — programovateľnou náhradou bez kryptografie, naviazanou na kontrakt PasskeyService — a vráti ju na asercie. Registračné a prihlasovacie controllery tak otestujete bez simulovania kryptografie autentifikátora. Nevykonáva dekódovanie CBOR/COSE, overenie podpisu ani kontrolu challenge a platí len pre daný test. Vidí ju fasáda, injektovaný PasskeyService aj metódy modelu:

- Ceremónie sa zaznamenajú, nevykonajú: register() uloží kľúč z factory a authenticate() vráti naprogramovaný výsledok. Možnosti sa zostavia ako skutočné, až na pripravené ID ceremónie, challenge a relying party (localhost / Fake): uplatnia každé nastavenie pre jedno volanie, predvolené hodnoty preberú z passkeys.\* (časový limit, overenie používateľa, rezidentný kľúč, atestácia, algoritmy) a pre Passkeys::for($user) uvedú aktívne kľúče účtu v excludeCredentials / allowCredentials. Nikdy nevyžadujú rp.id ani origins a možnosti registrácie dekódujú identifikátor používateľa rovnako ako skutočná služba, takže poškodený identifikátor sa odmietne aj tu.
- Vedľajšie účinky zostávajú skutočné: register() náhrady uloží kľúč s last\_used\_at null a spustí PasskeyRegistered; úspešné authenticate() zapíše last\_used\_at (počítadlo sa neposunie) a spustí PasskeyAuthenticated. Obe idú cez dispečer udalostí aplikácie, takže vaše listenery sa spustia, pokiaľ ich v teste nepotlačíte cez Event::fake(). Naprogramované zlyhanie nič nezapíše ani nespustí.
- Zaznamenajú sa aj volania cez metódy modelu (registerPasskey() a ďalšie) — idú cez Passkeys::for($this).
- rename() a revoke() stále spúšťajú skutočné akcie s kontrolou vlastníctva — vrátane zápisov a udalostí PasskeyRenamed / PasskeyRevoked — a po úspechu sa zaznamenajú.
- Čítanie (all(), find(), count(), exists()) ide do databázy; attestationFormats() vráti formáty skutočného registra.

```php
use RoundlyConsulting\Passkeys\Facades\Passkeys;

$fake = Passkeys::fake();

// The fake skips the crypto, not your controller's parsing: RegistrationResponseData::fromArray()
// still needs the browser's shape with base64url members — any bytes will do.
$this->postJson('/passkeys', [
    'id' => 'AAAA',
    'rawId' => 'AAAA',
    'type' => 'public-key',
    'response' => ['clientDataJSON' => 'e30', 'attestationObject' => 'oA'],
])->assertCreated();

$fake->assertRegisteredFor($user);

$this->deleteJson("/passkeys/{$passkey->id}")->assertNoContent();
$fake->assertRevoked($passkey);
$fake->assertNothingRenamed();

// programmable outcomes:
Passkeys::fake()->rejectAuthentication();          // authenticate() throws CredentialNotFound
Passkeys::fake()->authenticatesAs($passkey);       // authenticate() returns it — if still stored, unrevoked and owned
Passkeys::fake()->failRegistrationWith($exception);
```

## Programovateľné výsledky

| Metóda | Efekt |
| --- | --- |
| `acceptRegistration()` | register() uloží pre používateľa kľúč ES256 z factory (predvolené). |
| `failRegistrationWith($e)` | register() namiesto uloženia vyhodí zadanú PasskeyException. |
| `acceptAuthentication()` | authenticate() uspeje (predvolené). |
| `rejectAuthentication()` | authenticate() vyhodí CredentialNotFound. |
| `authenticatesAs($passkey)` | authenticate() vráti presne tento kľúč — rovnako ako skutočná služba ho odmietne, ak je odvolaný, nikdy nebol uložený alebo už nepatrí svojmu vlastníkovi. Vytvorte ho cez Passkey::factory()->forAuthenticatable($user). |

## Čo náhrada odmietne

Náhrada odmietne to, čo skutočné overovanie odmieta bez kryptografie, a v rovnakom poradí: kľúč musí byť stále uložený a neodvolaný, musí stále patriť svojmu vlastníkovi a musí spĺňať AuthenticationExpectation. Odmietnutie sa zaznamená ako neúspešné prihlásenie a vyhodí CredentialNotFound. Kontrola vlastníka je tá istá ako pri skutočnom overovaní — vlastník musí existovať, nesmie byť zmazaný cez soft delete a musí stále mať identifikátor používateľa kľúča — a platí pre kľúč z authenticatesAs() aj pre posledný kľúč zaregistrovaný cez náhradu. Kľúč, ktorého typ vlastníka neoznačuje žiadny model, sa odmietne rovnako.

Výnimkou je jediný kľúč: ten, ktorý si náhrada vytvorí sama, keď nič nepripravíte — bez authenticatesAs() a bez registrácie cez náhradu. Zastupuje „akýkoľvek platný kľúč“, preto sa jeho zástupný vlastník nekontroluje. Prihlásenie pripravte s kľúčom, ktorý patrí svojmu vlastníkovi: Passkey::factory()->forAuthenticatable($user) mu dá identifikátor používateľa, kým samotné Passkey::factory()->create() sa odmietne.

## Asercie

| Asercia | Prejde, keď |
| --- | --- |
| `assertRegistered()` | Zaznamenala sa aspoň jedna registrácia. |
| `assertRegisteredFor($user)` | Zaznamenala sa registrácia pre $user. |
| `assertNothingRegistered()` | Nezaznamenala sa žiadna registrácia. |
| `assertRegistrationCount($n)` | Zaznamenalo sa presne $n registrácií. |
| `assertAuthenticated()` | Zaznamenalo sa aspoň jedno úspešné prihlásenie. |
| `assertAuthenticatedFor($user)` | Zaznamenalo sa úspešné prihlásenie pre $user. |
| `assertAuthenticationFailed()` | Aspoň jedno prihlásenie zlyhalo. |
| `assertAuthenticationCount($n)` | Zaznamenalo sa presne $n prihlásení. |
| `assertRenamed(?$passkey, ?$name)` | Zaznamenalo sa premenovanie — tohto kľúča a/alebo na tento názov, ak ich zadáte. |
| `assertNothingRenamed()` | Nezaznamenalo sa žiadne premenovanie. |
| `assertRevoked(?$passkey)` | Zaznamenalo sa odvolanie — tohto kľúča, ak ho zadáte. |
| `assertNothingRevoked()` | Nezaznamenalo sa žiadne odvolanie. |

Asercie vyhadzujú PasskeyAssertionFailed — výnimku balíka, nie PHPUnit aserciu — takže fungujú v akomkoľvek test runneri. Náhrada rešpektuje AuthenticationExpectation rovnako ako skutočné overovanie a for($user)->authenticate() viaže výsledok na daný účet — kľúč nesprávneho vlastníka sa zaznamená ako neúspech a vyhodí CredentialNotFound:

```php
use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Passkeys\Events\PasskeyRegistered;
use RoundlyConsulting\Passkeys\Exceptions\CredentialAlreadyRegistered;
use RoundlyConsulting\Passkeys\Models\Passkey;

// A rejected sign-in
$fake = Passkeys::fake()->rejectAuthentication();
$this->postJson('/login/passkey', $payload)->assertUnauthorized();
$fake->assertAuthenticationFailed();

// A registration failure surfaced to the client
$fake = Passkeys::fake()->failRegistrationWith(CredentialAlreadyRegistered::make());
$this->actingAs($user)->postJson('/passkeys', $payload)->assertStatus(422);
$fake->assertNothingRegistered();

// Sign-in resolves to a specific credential
$passkey = Passkey::factory()->es256()->forAuthenticatable($user)->create();
Passkeys::fake()->authenticatesAs($passkey);
$this->postJson('/login/passkey', $payload)->assertOk();

// A deleted or soft-deleted account can't sign in
$passkey = Passkey::factory()->es256()->forAuthenticatable($user)->create();
$fake = Passkeys::fake()->authenticatesAs($passkey);
$user->delete();
$this->postJson('/login/passkey', $payload)->assertUnauthorized();
$fake->assertAuthenticationFailed();

// Your listener runs on a fake registration
Event::fake([PasskeyRegistered::class]);
Passkeys::fake();
$this->actingAs($user)->postJson('/passkeys', $payload)->assertCreated();
Event::assertDispatched(PasskeyRegistered::class);
```

## Skutočné ceremónie s virtuálnym autentifikátorom

Ak chcete v testoch skutočné overovanie — challenge, origin, hash RP ID, príznaky, podpis, počítadlo, viazanie na používateľa — použite VirtualAuthenticator, softvérový autentifikátor ES256 s atestáciou none:

```php
use RoundlyConsulting\Passkeys\DataTransferObjects\AuthenticationOptionsOverrides;
use RoundlyConsulting\Passkeys\Enums\UserVerification;
use RoundlyConsulting\Passkeys\Facades\Passkeys;
use RoundlyConsulting\Passkeys\Testing\VirtualAuthenticator;

$authenticator = VirtualAuthenticator::es256();   // rpId from the options, origin from config
$keys = Passkeys::for($user);

$keys->register($authenticator->register($keys->registrationOptions()));

$passkey = $keys->authenticate($authenticator->assert($keys->authenticationOptions()));

// Prove your step-up really demands user verification:
$options = $keys->authenticationOptions(new AuthenticationOptionsOverrides(userVerification: UserVerification::Required));
$keys->authenticate($authenticator->assert($options, userVerified: false)); // UserVerificationRequired

$authenticator->assert($options, signCount: 3);   // explicit counter, e.g. a cloned key
$authenticator->credentialId();                   // base64url, as stored in credential_id
```

- register($options, residentKey: false) simuluje neobjaviteľný kľúč bez userHandle v odpovediach — rovnako ako so skutočným prehliadačom teda odpovie len na možnosti vydané pre jeho používateľa (Passkeys::for($user)->authenticationOptions()); ceremónia bez mena ho odmietne.
- Počítadlo sa pri každom assert() zvýši o jedna, pokiaľ nezadáte signCount; userVerified: false pošle len prítomnosť používateľa.
- Odpovie na akékoľvek možnosti, takže test môže hrať aj útočníka a dokázať, že server odmietne.
- Len na testy: jeho kľúč je jednorazový materiál z TestKeys v crypto-for-laravel, v produkčnom kóde ho nikdy nepoužívajte. V runtime autoloade je len preto, aby ho mohli použiť testy iných balíkov — rovnako ako Passkeys::fake(). Na macOS s PHP z Homebrew môže generovanie kľúča vyžadovať OPENSSL\_CONF nasmerované na openssl.cnf z Homebrew.

## Factory

Passkey::factory() vytvára platné uložené kľúče pre vaše testy s použitím nakonfigurovaného modelu:

```php
use RoundlyConsulting\Passkeys\Models\Passkey;

$passkey = Passkey::factory()->es256()->forAuthenticatable($user)->create();
$rsa     = Passkey::factory()->rs256()->neverUsed()->forAuthenticatable($user)->create();
```

| Stav | Efekt |
| --- | --- |
| `es256()` | Platný verejný COSE kľúč ES256 (P-256). |
| `rs256()` | Platný verejný COSE kľúč RS256 (RSA-2048). |
| `withCredentialId($id)` | Kľúč s explicitným ID a jeho hashom. |
| `forAuthenticatable($model)` | Kľúč vlastnený konkrétnym modelom. Model s HasPasskeys mu dá aj svoj identifikátor používateľa (ak ho ešte nemá, vygeneruje sa), rovnako ako skutočná registrácia; iný model ponechá náhodný identifikátor. |
| `neverUsed()` | sign\_count = 0, last\_used\_at = null. |

Bez forAuthenticatable() má kľúč z factory zástupného vlastníka (morph typ user, náhodné ID), ktorému nezodpovedá žiadny účet, takže prihlásenie ho odmietne — v náhrade aj pri skutočnom overovaní.

## Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

[Ďalšie spôsoby podpory vrátane kryptomien](https://roundly-consulting.com/sk/podporte-nas.md)

Odoslaním daru súhlasíte s našimi [podmienkami prijímania darov](https://roundly-consulting.com/sk/podmienky-darov.md).

[Podporte našu open-source prácu (otvorí sa v novej karte)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Pridajte sa k nám na Patreone (otvorí sa v novej karte)](https://www.patreon.com/cw/roundly)

## Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.

[Ponuka do 48 hodín](https://roundly-consulting.com/sk/kontakt.md) [Prezrieť všetky balíky](https://roundly-consulting.com/sk/open-source/navody/passkeys-for-laravel.md)
