---
url: 'https://www.corbado.com/id/blog/pengujian-e2e-passkeys-playwright-webauthn-virtual-authenticator'
title: 'Pengujian E2E Passkey dengan Playwright melalui WebAuthn Virtual Authenticator'
description: 'Pelajari cara menyiapkan pengujian E2E untuk passkey di berbagai browser dengan Playwright, Nightwatch, Selenium, dan Puppeteer menggunakan WebAuthn virtual authenticator.'
lang: 'id'
author: 'Anders'
date: '2025-06-17T16:16:51.862Z'
lastModified: '2026-03-25T10:47:29.990Z'
keywords: 'pengujian e2e, tes end-to-end, tes end-2-end'
category: 'Passkeys Implementation'
---

# Pengujian E2E Passkey dengan Playwright melalui WebAuthn Virtual Authenticator

> **Misi kami adalah menjadikan Internet tempat yang lebih aman**, dan standar login baru,
> passkey, menyediakan solusi yang unggul untuk mencapainya. Itulah mengapa kami ingin
> membantu Anda memahami passkey dan karakteristiknya dengan lebih baik.

## 1. Pendahuluan: Pengujian E2E Passkey

Passkey menjadi semakin diterima secara luas sebagai metode
[autentikasi](https://www.corbado.com/id/blog/cara-menjadi-sepenuhnya-tanpa-password), dengan mengandalkan Web
Authentication (WebAuthn) sebagai standar dasarnya. Popularitasnya yang meningkat cukup
baru, yang membuat dokumentasi dan sumber daya lainnya relatif langka. Hal ini, ditambah
dengan sifat implementasi passkey yang kompleks, dapat menyulitkan developer untuk
menemukan informasi yang relevan tentang perancangan, implementasi, dan terutama pengujian
passkey untuk platform dan layanan mereka.

Panduan ini bertujuan untuk mengisi celah tersebut, dengan fokus pada aspek-aspek WebAuthn
virtual [authenticator](https://www.corbado.com/glossary/authenticator) yang tidak dibahas secara menyeluruh
dalam dokumentasi resminya. Misalnya, kami membahas opsi konfigurasi untuk virtual
[authenticator](https://www.corbado.com/glossary/authenticator) yang tidak dapat dijelaskan dengan sendirinya
dalam dokumentasi, serta solusi untuk kasus penggunaan tertentu yang tidak disediakan
solusi yang mudah oleh virtual [authenticator](https://www.corbado.com/glossary/authenticator). Selain itu,
panduan ini juga bermanfaat bagi developer yang hanya mencari contoh yang mudah diikuti
untuk menggunakan virtual authenticator dalam kode pengujian.

Panduan kami menggunakan contoh dari
[Playwright](https://www.corbado.com/blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator) untuk
memberikan panduan sederhana untuk menguji implementasi passkey secara efektif di proyek
Anda. [Playwright](https://www.corbado.com/blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator)
adalah kerangka kerja pengujian end-to-end (E2E) yang menggunakan Chrome DevTools Protocol
(CDP) sebagai protokol untuk automasi browser. Jika Anda secara khusus mencari contoh
teknis pengujian passkey di
[Playwright](https://www.corbado.com/blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator), Anda
dapat langsung melompat ke Bagian 5. Di sisi lain, jika Anda menggunakan kerangka kerja
pengujian E2E lain seperti
[Puppeteer](https://www.corbado.com/blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator) atau
[Selenium](https://www.corbado.com/blog/selenium-passkeys-testing-nodejs) dan ingin menguji passkey pada kerangka
kerja ini, implementasi kode pengujian akan identik atau sangat mirip dengan contoh yang
diberikan dalam panduan ini, tergantung pada kerangka kerja mana yang Anda gunakan. Di
bagian selanjutnya, kami memberikan latar belakang tentang berbagai kerangka kerja E2E dan
seberapa relevan panduan ini untuk kerangka kerja tersebut.

## 2. Latar Belakang: Automasi Browser dan Kerangka Kerja Pengujian E2E

### 2.1. Apa itu Automasi Browser?

Automasi browser, seperti namanya, adalah proses mengotomatiskan tindakan pengguna yang
berulang di browser untuk tujuan scraping data web atau dalam kasus kami, menguji aplikasi
web. WebDriver dan Chrome DevTools Protocol (CDP) adalah dua protokol automasi browser
utama yang relevan untuk panduan ini, karena masing-masing menyediakan implementasi
WebAuthn virtual authenticator.

### 2.2. Apa itu WebDriver?

WebDriver adalah antarmuka yang dikendalikan dari jarak jauh yang dapat dilihat sebagai
perantara dalam komunikasi antara klien dan browser. Fokus protokol ini adalah untuk
menyediakan antarmuka yang netral terhadap platform dan bahasa yang mendukung semua
browser utama, termasuk yang tidak berbasis Chromium seperti Firefox dan Safari. Karena
antarmuka WebDriver perlu mengelola koneksi dengan klien serta dengan browser, pendekatan
ini mengorbankan kecepatan dan stabilitas dengan imbalan jangkauan dukungan browser yang
lebih luas (yaitu, flakiness yang lebih tinggi). Klien WebDriver yang terkenal termasuk
[Selenium](https://www.corbado.com/blog/selenium-passkeys-testing-nodejs) dan
[Nightwatch](https://www.corbado.com/blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator).

![Passkeys Playwright WebDriver Client](https://www.corbado.com/website-assets/66090bb89296b283f07f69eb_passkeys_playwright_webdriver_client_1efc6dec0e.jpg)

Diambil dari jankaritech

### 2.3. Apa itu Chrome DevTools Protocol (CDP)?

Chrome DevTools Protocol (CDP), di sisi lain, tidak memiliki perantara seperti antarmuka
WebDriver antara klien dan browser. Selain itu, komunikasi antara klien dan browser
terjadi melalui koneksi socket, berbeda dengan koneksi HTTP yang lebih lambat antara klien
dan antarmuka WebDriver pada pendekatan sebelumnya. Poin-poin ini membuat CDP jauh lebih
cepat dan tidak terlalu flaky dibandingkan WebDriver. Kelemahannya adalah protokol ini
hanya didukung untuk browser berbasis Chromium seperti Chrome dan Edge. Playwright dan
[Puppeteer](https://www.corbado.com/blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator) adalah
contoh klien yang menggunakan CDP untuk berkomunikasi dengan browser.

![Passkeys PlayWright CDP Client](https://www.corbado.com/website-assets/66090be6820f38fba3e156f3_passkeys_playwright_cdp_client_44e000d341.jpg)

Diambil dari jankaritech

### 2.4. Puppeteer & Playwright sebagai Kerangka Kerja Pengujian E2E Berbasis CDP

[Puppeteer](https://www.corbado.com/blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator), mirip
dengan Playwright, adalah kerangka kerja E2E yang dibangun langsung di atas CDP. Ini
berarti bahwa Puppeteer dan Playwright keduanya menggunakan implementasi WebAuthn virtual
authenticator yang sama dan komunikasi API menggunakan WebAuthn virtual authenticator
melalui koneksi socket juga identik.

Untuk mendemonstrasikannya, kami membandingkan kode pengujian di Playwright dan Puppeteer
untuk memanggil metode getCredentials yang mengembalikan daftar semua kredensial yang
terdaftar di virtual authenticator sejauh ini. Kami juga melampirkan event listener
sederhana untuk event credentialAdded yang dipicu ketika kredensial passkey berhasil
didaftarkan. Jangan terintimidasi oleh detail implementasinya, karena akan dijelaskan di
bagian selanjutnya. Contoh-contoh ini hanya untuk menunjukkan seberapa mirip implementasi
antara kedua kerangka kerja tersebut.

**Playwright:**

```js
const client = await page.context().newCDPSession(page);
await client.send('WebAuthn.enable');
const authenticatorId = const result = await client.send('WebAuthn.addVirtualAuthenticator', { options });

...

// get all credentials registered in the virtual authenticator
const result = await client.send('WebAuthn.getCredentials', { authenticatorId });
console.log(result.credentials);

// add a listener to the credentialAdded event to output a log to the console whenever a passkey credential is registered
client.on('WebAuthn.credentialAdded', () => {
  console.log('Credential Added!');
});
```

**Puppeteer:**

```js
const client = await page.target().createCDPSession();
await client.send('WebAuthn.enable');
const authenticatorId = const result = await client.send('WebAuthn.addVirtualAuthenticator', { options });

...

// get all credentials registered in the virtual authenticator
const result = await client.send('WebAuthn.getCredentials', { authenticatorId });
console.log(result.credentials);

// add a listener to the credentialAdded event to output a log to the console whenever a passkey credential is registered
client.on('WebAuthn.credentialAdded', () => {
  console.log('Credential Added!');
});
```

Meskipun metode untuk menginisialisasi sesi CDP di awal kode pengujian sedikit berbeda,
memanggil metode dan menangani event di API WebAuthn virtual authenticator CDP adalah
identik. Ini berarti jika Anda ingin menggunakan WebAuthn virtual authenticator di
Puppeteer, Anda dapat mengikuti panduan ini baris demi baris.

### 2.5. Selenium & Nightwatch sebagai Kerangka Kerja Pengujian E2E Berbasis WebDriver

[Selenium](https://www.corbado.com/blog/selenium-passkeys-testing-nodejs) dan
[Nightwatch](https://www.corbado.com/blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator) adalah
kerangka kerja pengujian E2E yang mengandalkan WebDriver untuk automasi browser. Meskipun
implementasi WebAuthn virtual authenticator untuk WebDriver terpisah dari implementasinya
untuk CDP, spesifikasi API mereka serupa. Untuk hampir setiap metode di API WebAuthn
virtual authenticator CDP, Anda dapat menemukan metode yang sesuai di API WebAuthn virtual
authenticator WebDriver. Namun, satu hal yang perlu diperhatikan adalah meskipun
dimungkinkan untuk melampirkan event listener saat passkey berhasil ditambahkan atau
ditegaskan di API WebAuthn virtual authenticator CDP, hal ini tidak dimungkinkan di rekan
WebDriver-nya.

**Selenium:**

```js
const driver = await new Builder().forBrowser('chrome').build();
const options = new VirtualAuthenticatorOptions();
await driver.addVirtualAuthenticator(options);

...

// get all credentials registered in the virtual authenticator
const credentials = await driver.getCredentials();
```

Terbukti bahwa sintaks untuk menyiapkan instance virtual authenticator dan melakukan
panggilan API berbeda dari implementasi CDP yang sesuai. Namun, karena spesifikasi API
dari kedua WebAuthn virtual authenticator sangat mirip, akan layak untuk mengikuti panduan
ini untuk menulis implementasi yang sesuai pada kerangka kerja pengujian E2E berbasis
WebDriver.

### 2.6. Cypress sebagai Kerangka Kerja Pengujian E2E dengan Native Scripting

[Cypress](https://www.corbado.com/blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator) adalah
kerangka kerja pengujian E2E yang tidak dibangun terutama di atas WebDriver atau CDP
seperti kerangka kerja yang disebutkan di atas. Ia menggunakan
[JavaScript](https://www.corbado.com/id/blog/aplikasi-crud-react-express-mysql) asli untuk berkomunikasi dengan
browser. Namun, ia menyediakan akses tingkat rendah ke CDP, yang berarti dimungkinkan
untuk mengirim perintah CDP mentah untuk memanfaatkan WebAuthn virtual authenticator CDP.

Karena sintaks untuk akses tingkat rendah ini membosankan dan sangat berbeda dari contoh
di atas, kami tidak akan membahas detailnya dalam panduan ini. Namun, informasi lebih
lanjut tentang cara memanggil perintah CDP di
[Cypress](https://www.corbado.com/blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator) dijelaskan
dalam panduan ini. Konsep gambaran besar untuk menggunakan WebAuthn virtual authenticator
CDP yang disajikan dalam panduan ini masih relevan bagi mereka yang ingin menguji passkey
di [Cypress](https://www.corbado.com/blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator).

## 3. Apa yang Membuat Pengujian E2E Passkey dengan Playwright Menjadi Masalah?

Ada banyak alasan mengapa pengujian implementasi passkey secara alami lebih menantang
daripada tindakan pengguna lain yang lebih sederhana di lingkungan web. Kebutuhan untuk
menangani interaksi pengguna dinamis yang terlibat dengan
[autentikasi biometrik](https://www.corbado.com/id/faq/apa-itu-passkeys), seperti pemindaian sidik jari atau
pengenalan wajah, menambah lapisan kompleksitas yang mungkin tidak praktis untuk ditangani
secara detail saat menulis pengujian. Karena
[keamanan](https://www.corbado.com/id/blog/cara-mengaktifkan-passkey-android) secara alami menjadi perhatian
utama dalam konteks [autentikasi](https://www.corbado.com/id/blog/cara-menjadi-sepenuhnya-tanpa-password), juga
perlu untuk memastikan bahwa
[autentikasi passkey](https://www.corbado.com/id/blog/penyedia-passkey-aaguid-adopsi) terintegrasi dengan mulus
di berbagai browser dan perangkat tanpa ada ruang untuk kerentanan
[keamanan](https://www.corbado.com/id/blog/cara-mengaktifkan-passkey-android).

## 4. WebAuthn Virtual Authenticator Memungkinkan Pengujian E2E Passkey

Menyederhanakan kompleksitas penanganan interaksi pengguna dinamis yang terlibat dalam
operasi passkey, serta menguji integrasinya ke berbagai browser dan perangkat, menjadi
lebih mudah menggunakan WebAuthn virtual authenticator.

### 4.1. Apa itu WebAuthn Virtual Authenticator?

WebAuthn virtual authenticator adalah representasi perangkat lunak dari model
authenticator yang ditentukan dalam standar WebAuthn. Ini meniru perilaku perangkat
authenticator fisik, seperti
[kunci keamanan perangkat keras](https://www.corbado.com/id/blog/kunci-keamanan-perangkat-keras-fido2-terbaik)
(misalnya [YubiKey](https://www.corbado.com/glossary/yubikey)) atau pemindai biometrik (misalnya yang digunakan
di [Face ID](https://www.corbado.com/faq/is-face-id-passkey), Touch ID, atau
[Windows Hello](https://www.corbado.com/glossary/windows-hello)), tetapi beroperasi sepenuhnya dalam perangkat
lunak (jadi tidak ada [autentikasi](https://www.corbado.com/id/blog/cara-menjadi-sepenuhnya-tanpa-password) fisik
atau pemindaian biometrik yang terlibat).

### 4.2. Apa Manfaat WebAuthn Virtual Authenticator?

Ada dua manfaat utama dari WebAuthn virtual authenticator.

#### 4.2.1. Pengujian Otomatis dengan WebAuthn Virtual Authenticator

Karena WebDriver dan CDP adalah alat automasi browser, jelas bahwa kasus penggunaan utama
dari implementasi WebAuthn virtual authenticator dalam protokol ini adalah pengujian
otomatis. Dengan memanfaatkan protokol ini, virtual authenticator memungkinkan pengujian
fungsionalitas passkey yang sederhana namun komprehensif di lingkungan yang terkontrol
seperti kerangka kerja pengujian E2E (misalnya Playwright, Cypress,
[Nightwatch](https://www.corbado.com/blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator)).

#### 4.2.2. Pengujian Manual dan Demonstrasi dengan WebAuthn Virtual Authenticator

WebAuthn virtual authenticator CDP juga dapat diakses melalui DevTools browser Chrome, dan
dapat digunakan untuk pengujian manual atau hanya untuk tujuan demonstrasi. Dengan fitur
ini Anda dapat mensimulasikan input passkey pada perangkat yang tidak mendukung passkey
secara native. Sejalan dengan itu, juga dimungkinkan untuk mensimulasikan lingkungan yang
tidak didukung passkey pada perangkat yang mendukung passkey.

![Passkeys Playwright Virtual WebAuthn Authenticator](https://www.corbado.com/website-assets/66090c090678d8241d6e9f67_passkeys_playwright_virtual_webauthn_authenticator_3d1fa5c566.jpg)

Tangkapan layar di atas menunjukkan contoh penggunaan virtual authenticator di Chrome
untuk tujuan pengujian manual atau demonstrasi. Anda dapat melihat bahwa berbagai opsi
konfigurasi untuk virtual authenticator dimungkinkan, dan penambahan serta penghapusan
kredensial juga dapat dilacak. Rujuk ke panduan ini dari Google untuk informasi lebih
lanjut tentang penggunaan virtual authenticator di browser Anda, termasuk opsi konfigurasi
dan nilai yang direkomendasikan untuk masing-masing.

### 4.3. Apa Kekurangan WebAuthn Virtual Authenticator?

Meskipun WebAuthn virtual authenticator adalah solusi yang elegan untuk menguji
implementasi passkey, ada beberapa kekurangan yang perlu diperhatikan.

#### 4.3.1. Ketidakmampuan untuk Mensimulasikan Fungsionalitas Spesifik Perangkat Keras

Sebagai solusi yang murni berbasis perangkat lunak, WebAuthn virtual authenticator tidak
dapat mereplikasi karakteristik perangkat keras yang unik dan fitur
[keamanan](https://www.corbado.com/id/blog/cara-mengaktifkan-passkey-android) dari authenticator fisik. Perbedaan
antara menggunakan berbagai [platform authenticator](https://www.corbado.com/glossary/platform-authenticator)
(yang terpasang di perangkat, seperti pemindai biometrik di smartphone) dan berbagai
cross-[platform authenticator](https://www.corbado.com/glossary/platform-authenticator) (yang merupakan perangkat
eksternal, seperti
[kunci keamanan perangkat keras](https://www.corbado.com/id/blog/kunci-keamanan-perangkat-keras-fido2-terbaik))
tidak dapat disimulasikan menggunakan WebAuthn virtual authenticator. Meskipun
penyederhanaan black-box dari kompleksitas yang terlibat dengan berbagai jenis platform
dan cross-[platform authenticator](https://www.corbado.com/glossary/platform-authenticator) adalah salah satu
keuntungan menggunakan WebAuthn virtual authenticator, jika Anda ingin mensimulasikan dan
menguji nuansa dari berbagai jenis authenticator, solusi lain harus dieksplorasi.

#### 4.3.2. Dokumentasi yang Jarang dan Masalah Teknis yang Belum Terselesaikan

Mengingat adopsi WebAuthn yang relatif baru dan kebaruan teknologi passkey, ekosistem di
sekitar virtual authenticator masih dalam tahap pematangan. Hal ini mengakibatkan
kelangkaan dokumentasi yang komprehensif dan tantangan teknis yang belum terselesaikan,
terutama dalam konteks mengintegrasikan virtual authenticator dengan kerangka kerja
pengujian otomatis. Panduan ini bertujuan untuk mengatasi masalah ini dengan memberikan
wawasan komprehensif tentang pengujian passkey di lingkungan pengujian otomatis, sambil
juga berfokus pada mengatasi ketidaknyamanan yang masih ada dalam menggunakan alat-alat
ini dan menyajikan solusi untuk masalah-masalah ini.

## 5. Cara Menyiapkan WebAuthn Virtual Authenticator di Playwright

Setelah instalasi Playwright dan dependensinya berhasil, Anda dapat langsung mulai menulis
pengujian pertama Anda dengan membuat file dengan nama yang diakhiri dengan .spec.ts atau
.test.ts dengan konten berikut:

```js
import { test, expect } from "@playwright/test";

test("my first test", async ({ page }) => {
    await page.goto("https://passkeys.eu");

    // start simulating user actions
});
```

Untuk menggunakan WebAuthn virtual authenticator di Playwright, cukup dengan memulai sesi
CDP dan melampirkan virtual authenticator di awal kasus pengujian, sebagai berikut:

```js
test('signup with passkey', async ({ page }) => {
  // Initialize a CDP session for the current page
  const client = await page.context().newCDPSession(page);

  // Enable WebAuthn environment in this session
  await client.send('WebAuthn.enable');

  // Attach a virtual authenticator with specific options
  const result = await client.send('WebAuthn.addVirtualAuthenticator', {
    options: {
      protocol: 'ctap2',
      transport: 'internal',
      hasResidentKey: true,
      hasUserVerification: true,
      isUserVerified: true,
      automaticPresenceSimulation: false,
    },
  });
  const authenticatorId = result.authenticatorId;

  // Further test steps to simulate user interactions and assertions
...
});
```

Opsi untuk mengonfigurasi WebAuthn virtual authenticator:

- **protocol:** Opsi ini menentukan protokol yang digunakan oleh virtual authenticator.
  Nilai yang mungkin adalah "ctap2" dan "u2f"
- **transport:** Opsi ini menentukan jenis authenticator yang disimulasikan oleh virtual
  authenticator. Nilai yang mungkin adalah "usb", "nfc", "ble", dan "internal". Jika
  diatur ke "internal", ini mensimulasikan platform authenticator, sementara nilai lain
  mensimulasikan cross-platform authenticator.
- **hasResidentKey:** Mengaturnya ke true mendukung
  [Resident Key](https://www.corbado.com/blog/webauthn-resident-key-discoverable-credentials-passkeys) (yaitu,
  client-side
  [discoverable credential](https://www.corbado.com/blog/webauthn-resident-key-discoverable-credentials-passkeys)).
- **hasUserVerification:** Mengaturnya ke true mendukung
  [User Verification](https://www.corbado.com/blog/webauthn-user-verification). Mengatur ini sebagai true
  direkomendasikan karena memungkinkan simulasi input passkey yang berhasil dan gagal.
- **isUserVerified:** Mengaturnya ke true meniru skenario autentikasi yang berhasil,
  sedangkan false meniru kegagalan autentikasi, seperti ketika pengguna membatalkan input
  passkey. Perhatikan bahwa pengaturan ini hanya efektif ketika hasUserVerification diatur
  ke true.
- **automaticPresenceSimulation:** Ketika diatur ke true, input passkey terjadi secara
  otomatis dan segera setelah ada prompt autentikasi. Sebaliknya, mengaturnya ke false
  memerlukan inisiasi manual simulasi
  [autentikasi passkey](https://www.corbado.com/id/blog/penyedia-passkey-aaguid-adopsi) dalam kode pengujian.
  Memilih simulasi manual (false) direkomendasikan karena dua alasan:
    - **Meningkatkan keterbacaan kode pengujian:** Simulasi otomatis dapat mengaburkan
      pemahaman alur pengujian, karena upaya autentikasi disimulasikan tanpa pemicu
      eksplisit dalam kode pengujian.
    - **Menghindari perilaku yang tidak diinginkan:** Simulasi otomatis berarti bahwa
      input passkey akan dipicu bahkan jika penguji tidak menyadari bahwa passkey diminta.
      Ini terutama menjadi masalah untuk [Conditional UI](https://www.corbado.com/glossary/conditional-ui) yang
      akan lebih mudah diabaikan oleh penguji.

## 6. Kasus Penggunaan WebAuthn Virtual Authenticator

Di bagian ini, kita akan menjelajahi penggunaan metode dan event WebAuthn virtual
authenticator dalam konteks kasus penggunaan umum dan khusus.

### 6.1. Cara Mensimulasikan Upaya Input Passkey di Playwright

Ini mungkin tugas yang paling penting namun membingungkan saat menggunakan WebAuthn
virtual authenticator dalam kode pengujian, karena tidak ada metode bawaan yang eksplisit
untuk memicu input passkey. Solusinya terletak pada opsi konfigurasi WebAuthn virtual
authenticator yaitu, isUserVerified dan automaticPresenceSimulation. Dengan opsi ini kita
dapat mensimulasikan interaksi pengguna ini melalui dua pendekatan berbeda yang dijelaskan
di bawah ini.

#### 6.1.1. Pendekatan 1: Simulasi otomatis dengan automaticPresenceSimulation diatur ke true

**Kasus 1: Mensimulasikan input passkey yang berhasil**

```js
test('signup with passkey', async ({ page }) => {
...

  await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in');
  await page.getByRole('button', { name: 'Login' }).click();
  // successful passkey input is automatically simulated (isUserVerified=true)
  await expect(page.getByRole('heading', { level: 1 })).toHaveText('Welcome!');

...
});
```

Mensimulasikan input passkey yang berhasil biasanya tidak memerlukan baris tambahan dalam
kode pengujian. Baris terakhir (await expect...) menunggu halaman berubah (dipicu oleh
input passkey yang berhasil secara implisit).

**Kasus 2: Mensimulasikan input passkey yang dibatalkan (yang tidak memicu perubahan pada
UI)**

Menguji input passkey yang gagal atau dibatalkan lebih rumit karena mungkin tidak
menyebabkan perubahan yang dapat diamati pada UI. Dengan kata lain, menunggu halaman
berubah seperti pada contoh sebelumnya tidak cukup untuk memastikan bahwa input passkey
telah selesai diproses. Memeriksa bahwa halaman tidak berubah setelah input passkey
implisit tidak ada artinya, karena pemeriksaan hampir pasti akan terjadi sebelum input
passkey selesai diproses. Meskipun virtual authenticator menyediakan cara untuk menunggu
input passkey yang berhasil diproses dengan mendengarkan emisi event (seperti yang akan
dibahas dalam pendekatan 2), saat ini tidak ada cara bawaan untuk mendeteksi input passkey
yang gagal atau dibatalkan. Solusinya adalah dengan menambahkan timeout keras untuk
menunggu operasi passkey selesai sebelum memeriksa bahwa UI memang tetap sama.

```js
test('signup with passkey', async ({ page }) => {
  // Simulate a set of user actions to trigger a passkey prompt
...

  await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in');

  // Simulate passkey input when prompted in the test
  await inputPasskey(async () => {
    await page.waitForTimeout(300);
    await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in');
  });

  // Further test steps
...
});
```

Dalam kedua kasus, keterbacaan kode pengujian dibatasi oleh sifat implisit dari operasi
passkey. Seperti yang disebutkan sebelumnya, akan mudah juga untuk mengabaikan kapan
[Conditional UI](https://www.corbado.com/glossary/conditional-ui) mungkin diminta, dalam hal ini operasi passkey
akan selesai secara otomatis tanpa sepengetahuan penguji.

#### 6.1.2. Pendekatan 2: Simulasi Manual dengan automaticPresenceSimulation diatur ke false

Memicu input passkey secara manual dengan mengubah nilai opsi automaticPresenceSimulation
menyelesaikan masalah yang dihadapi pada pendekatan sebelumnya, yaitu dalam hal
keterbacaan kode pengujian.

**Kasus 1: Mensimulasikan input passkey yang berhasil**

Cuplikan kode berikut mensimulasikan input passkey yang berhasil:

```js
async simulateSuccessfulPasskeyInput(operationTrigger: () => Promise<void>) {
  // initialize event listeners to wait for a successful passkey input event
  const operationCompleted = new Promise<void>(resolve => {
    client.on('WebAuthn.credentialAdded', () => resolve());
    client.on('WebAuthn.credentialAsserted', () => resolve());
  });

  // set isUserVerified option to true
  // (so that subsequent passkey operations will be successful)
  await client.send('WebAuthn.setUserVerified', {
    authenticatorId: authenticatorId,
    isUserVerified: true,
  });

  // set automaticPresenceSimulation option to true
  // (so that the virtual authenticator will respond to the next passkey prompt)
  await client.send('WebAuthn.setAutomaticPresenceSimulation', {
    authenticatorId: authenticatorId,
            enabled: true,
  });

  // perform a user action that triggers passkey prompt
  await operationTrigger();

  // wait to receive the event that the passkey was successfully registered or verified
  await operationCompleted;

  // set automaticPresenceSimulation option back to false
  await client.send('WebAuthn.setAutomaticPresenceSimulation', {
    authenticatorId,
            enabled: false,
  });
}
```

```js
test('signup with passkey', async ({ page }) => {
...

  // Simulate passkey input with a promise that triggers a passkey prompt as the argument
  await simulateSuccessfulPasskeyInput(() =>
          page.getByRole('button', { name: 'Create account with passkeys' }).click()
  );

...
});
```

Fungsi pembantu (helper function) mungkin cukup mengintimidasi saat Anda melihatnya untuk
pertama kali. Akan membantu untuk memahami bahwa semua kompleksitas teknis dalam
mensimulasikan operasi passkey diabstraksikan ke dalam fungsi pembantu. Ini berarti bahwa
ketika digunakan di dalam kode pengujian, itu membuat kode menjadi sederhana dan jelas,
seperti yang dapat dilihat pada cuplikan kode kedua di atas.

Dibandingkan dengan pendekatan implisit di Bagian 6.1.1, pendekatan eksplisit ini juga
meningkatkan keterbacaan kode. Ini akan sangat membantu ketika
[Conditional UI](https://www.corbado.com/glossary/conditional-ui) diminta, karena pendekatan eksplisit ini
mencegah penyelesaian operasi passkey yang tidak disengaja dan implisit tanpa
sepengetahuan developer.

Sekarang mari kita pahami setiap bagian dari fungsi pembantu.

Pertama, kita mendefinisikan promise operationCompleted yang menunggu event
WebAuthn.credentialAdded atau event WebAuthn.credentialAsserted, yang, seperti namanya,
dipancarkan ketika kredensial passkey berhasil didaftarkan atau diverifikasi. Promise ini
akan digunakan nanti.

Selanjutnya, opsi isUserVerified diatur ke true, sehingga operasi passkey berikutnya oleh
WebAuthn virtual authenticator akan berhasil. automaticPresenceSimulation juga diatur ke
true, sehingga WebAuthn virtual authenticator akan merespons prompt passkey berikutnya
dari halaman web.

Menunggu promise operationTrigger diperlukan untuk menghindari race condition. Race
condition terjadi ketika halaman web meminta passkey sebelum automaticPresenceSimulation
diatur ke true. Untuk mencegah ini, tindakan pengguna yang memicu prompt passkey harus
dilakukan setelah automaticPresenceSimulation diatur ke true. Dalam contoh di atas,
pengguna mengklik tombol bernama Create account with passkeys untuk memicu prompt passkey.

Setelah tindakan pengguna selesai, kita harus menunggu operasi passkey yang berhasil
selesai. Ini dilakukan dengan menunggu promise yang kita definisikan di awal fungsi
pembantu. Penyelesaian operasi passkey yang berhasil ditandai dengan pancaran event
WebAuthn.credentialAdded atau WebAuthn.credentialAsserted. Dalam contoh di atas, karena
pengguna mendaftarkan passkey, event WebAuthn.credentialAdded akan dipancarkan.

Akhirnya, opsi automaticPresenceSimulation diatur kembali ke false, untuk mencegah operasi
passkey yang tidak disengaja terjadi nanti dalam kode pengujian.

**Kasus 2: Mensimulasikan input passkey yang dibatalkan**

Untuk input passkey yang dibatalkan, kita harus membuat sedikit modifikasi pada
implementasi untuk kasus sebelumnya. Dalam kasus input passkey yang berhasil, ada event,
yaitu WebAuthn.credentialAdded dan WebAuthn.credentialAsserted, yang dipancarkan setelah
penyelesaian operasi. Namun, WebAuthn virtual authenticator tidak menyediakan event apa
pun untuk input passkey yang dibatalkan atau gagal. Jadi, kita harus menggunakan cara
alternatif untuk memeriksa penyelesaian operasi passkey yang dibatalkan atau gagal.

Cuplikan kode berikut mensimulasikan input passkey yang gagal:

```js
async simulateFailedPasskeyInput(operationTrigger: () => Promise<void>, postOperationCheck: () => Promise<void>) {
  // set isUserVerified option to false
  // (so that subsequent passkey operations will fail)
  await client.send('WebAuthn.setUserVerified', {
    authenticatorId: authenticatorId,
    isUserVerified: false,
  });

  // set automaticPresenceSimulation option to true
  // (so that the virtual authenticator will respond to the next passkey prompt)
  await client.send('WebAuthn.setAutomaticPresenceSimulation', {
    authenticatorId: authenticatorId,
            enabled: true,
  });

  // perform a user action that triggers passkey prompt
  await operationTrigger();

  // wait for an expected UI change that indicates the passkey operation has completed
  await postOperationCheck();

  // set automaticPresenceSimulation option back to false
  await client.send('WebAuthn.setAutomaticPresenceSimulation', {
    authenticatorId,
            enabled: false,
  });
}
```

```js

test('signup with passkey', async ({ page }) => {
  // Simulate a set of user actions to trigger a passkey prompt
...

  await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in');

  // Simulate passkey input when prompted in the test
  await inputPasskey(async () => {
    await page.waitForTimeout(300);
    await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in');
  });

  // Further test steps
...
});
```

Dalam fungsi pembantu, event listener diganti dengan parameter promise postOperationCheck
yang menunggu perubahan UI yang diharapkan terjadi sebelum automaticPresenceSimulation
dapat diatur kembali ke false.

Dalam kode pengujian, satu-satunya perbedaan adalah bahwa fungsi pembantu harus dipanggil
dengan promise tambahan yang memeriksa perubahan UI yang dimaksud. Dalam contoh di atas,
kami memeriksa bahwa [aplikasi web](https://www.corbado.com/id/blog/aplikasi-crud-react-express-mysql) telah
berhasil menavigasi ke halaman di mana header memiliki teks Something went wrong....

Seperti yang dibahas di Bagian 6.1.1, membatalkan input passkey mungkin tidak menyebabkan
perubahan yang dapat diamati pada UI. Seperti contoh yang diberikan di bagian itu, kita
harus menambahkan penantian keras (hard wait) sebelum memeriksa bahwa UI memang tetap sama
dalam kasus seperti itu:

```js
test('signup with passkey', async ({ page }) => {
...

  await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in');

  // Simulate passkey input with a promise that triggers a passkey prompt as the argument
  await simulateFailedPasskeyInput(
          () => page.getByRole('button', { name: 'Create account with passkeys' }).click(),
          async () => {
            await page.waitForTimeout(300);
            await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in');
          }
  );

...
});
```

### 6.2. Cara Menguji Pembuatan Passkey

Kenyamanan menggunakan WebAuthn virtual authenticator ditingkatkan oleh kemampuannya untuk
berperilaku seperti authenticator nyata dalam hal pembuatan atau penghapusan passkey oleh
[aplikasi web](https://www.corbado.com/id/blog/aplikasi-crud-react-express-mysql). Sebuah pengujian hanya perlu
melakukan tindakan pengguna untuk mensimulasikan pembuatan atau penghapusan passkey pada
[aplikasi web](https://www.corbado.com/id/blog/aplikasi-crud-react-express-mysql), dan WebAuthn virtual
authenticator secara otomatis memodifikasi informasi kredensial yang disimpannya tanpa
pekerjaan tambahan dari sisi kode pengujian.

Berikut adalah contoh kode pengujian yang memeriksa bahwa aplikasi web mendaftarkan
passkey baru ke authenticator dengan benar:

```js
test('signup with passkey', async ({ page }) => {
...

  // Confirm there are currently no registered credentials
  const result1 = await client.send('WebAuthn.getCredentials', { authenticatorId });
  expect(result1.credentials).toHaveLength(0);

  // Perform user actions to simulate creation of a passkey credential (e.g. user registration with passkey input)
...

  // Confirm the passkey was successfully registered
  const result2 = await client.send('WebAuthn.getCredentials', { authenticatorId });
  expect(result2.credentials).toHaveLength(1);

...
});
```

Menggabungkan cuplikan kode ini dengan cuplikan kode dari Bagian 6.1, kita dapat menguji
alur pendaftaran di halaman web demo kami. Video berikut adalah visualisasi pengujian
dalam mode UI Playwright:

[Watch on YouTube](https://www.youtube.com/watch?v=HqqRgds2T94)

### 6.3. Cara Menguji Verifikasi Passkey

Memverifikasi kredensial passkey dengan WebAuthn virtual authenticator bekerja mirip
dengan membuat passkey, di mana virtual authenticator secara otomatis melacak jumlah
verifikasi yang dilakukan menggunakan kredensial tertentu.

```js
test('login with passkey', async ({ page }) => {
...

  // Confirm there is only one credential, and save its signCount
  const result1 = await client.send('WebAuthn.getCredentials', { authenticatorId });
  expect(result1.credentials).toHaveLength(1);
  const signCount1 = result1.credentials[0].signCount;

  // Perform user actions to simulate verification of a passkey credential (e.g. login with passkey input)
...

  // Confirm the credential's new signCount is greater than the previous signCount
  const result2 = await client.send('WebAuthn.getCredentials', { authenticatorId });
  expect(result2.credentials).toHaveLength(1);
  expect(result2.credentials[0].signCount).toBeGreaterThan(signCount1);

...
});
```

Video berikut mendemonstrasikan pengujian untuk alur login di halaman web demo kami:

[Watch on YouTube](https://www.youtube.com/watch?v=f3Vj0Dd562A)

### 6.4. Cara Menguji Penghapusan Passkey

Menghapus passkey dari aplikasi web, di sisi lain, seharusnya tidak mengubah informasi apa
pun di dalam WebAuthn virtual authenticator. Aplikasi web seharusnya hanya dapat menghapus
kredensial yang disimpan di servernya sendiri. Hanya pengguna itu sendiri yang seharusnya
dapat secara sadar dan manual menghapus kredensial passkey dari WebAuthn virtual
authenticator.

```js
test('delete a registered passkey credential', async ({ page }) => {
...

  // Confirm there is currently one registered credential
  const result1 = await client.send('WebAuthn.getCredentials', { authenticatorId });
  expect(result1.credentials).toHaveLength(1);

  // Perform user actions to simulate deletion of a passkey credential
...

  // Deleting a passkey credential from a website should not remove the credential from the authenticator
  const result2 = await client.send('WebAuthn.getCredentials', { authenticatorId });
  expect(result2.credentials).toHaveLength(1);

...
});
```

Video berikut mendemonstrasikan pengujian untuk penghapusan kredensial passkey di halaman
web demo kami:

[Watch on YouTube](https://www.youtube.com/watch?v=QG5_wPMY9q8)

### 6.5. Cara Mensimulasikan Autentikasi Lintas Perangkat

Cara paling intuitif untuk mensimulasikan autentikasi lintas perangkat dari perangkat
kedua (yang belum memiliki passkey terdaftar) adalah dengan hanya menambahkan instance
baru dari WebAuthn virtual authenticator melalui perintah CDP, seperti ini:

```js
test('signup with passkey', async ({ page }) => {
...

  // add a virtual authenticator for the first device
  const authenticatorId1 = await client.send('WebAuthn.addVirtualAuthenticator', { options });

  // perform test actions of the first device
...

  // add a virtual authenticator for the second device
  const authenticatorId2 = await client.send('WebAuthn.addVirtualAuthenticator', { options });

  // perform test actions of the second device
..
});
```

Untuk menghindari kompleksitas mengelola ID dari beberapa virtual authenticator, juga
dimungkinkan untuk mensimulasikan perangkat baru dengan hanya menghapus kredensial dari
satu authenticator, dan menambahkannya kembali saat dibutuhkan:

```js

test('signup with passkey', async ({ page }) => {
...

  const result = await client.send('WebAuthn.getCredentials', { authenticatorId });
  const credential = result.credentials[0]; // assuming only one registered passkey
  const credentialId = credential.credentialId;
  await client.send('WebAuthn.removeCredential', { authenticatorId, credentialId });

  // Perform test actions of the second device which doesn't have a registered passkey
...

  // Call if it's necessary to simulate the first device which has a registered passkey
  await client.send('WebAuthn.addCredential', { credential });

  // Perform test actions of the first device
...
});
```

Pendekatan ini terutama dapat menyederhanakan implementasi dalam kasus di mana perangkat
baru perlu disimulasikan, tetapi perangkat lama tidak perlu digunakan lagi. Dalam hal ini,
Anda hanya perlu membersihkan kredensial dari virtual authenticator dan membuang
kredensialnya sama sekali:

```js
test('signup with passkey', async ({ page }) => {
...

  const result = await client.send('WebAuthn.getCredentials', { authenticatorId });
  const credential = result.credentials[0]; // assuming only one registered passkey
  const credentialId = credential.credentialId;
  await client.send('WebAuthn.clearCredentials', { authenticatorId });

  // Perform test actions of the second device which doesn't have a registered passkey
...
});
```

## 7. Alternatif untuk WebAuthn Virtual Authenticator

Menjelajahi alternatif untuk WebAuthn virtual authenticator dapat menawarkan fleksibilitas
dalam cara proses [autentikasi passkey](https://www.corbado.com/id/blog/penyedia-passkey-aaguid-adopsi) /
WebAuthn diuji dalam proyek.

### 7.1. Pengujian dengan Layanan Mock

Mengembangkan layanan atau endpoint mock dapat secara efektif mensimulasikan perilaku
autentikasi, menyederhanakan pengujian dengan mengabstraksi seluk-beluk mekanisme
autentikasi yang sebenarnya. Pendekatan ini sangat bermanfaat ketika layanan autentikasi
eksternal digunakan, memungkinkan fokus tetap pada integrasi dan fungsionalitas komponen
sistem tanpa harus mendalami spesifik autentikasi.

### 7.2. Pengujian Integrasi dengan Authenticator Nyata

Untuk pemeriksaan menyeluruh fungsionalitas autentikasi, menggunakan authenticator nyata
untuk pengujian integrasi memberikan wawasan terperinci tentang interaksi dengan kunci
keamanan perangkat keras (misalnya YubiKeys) atau perangkat biometrik (misalnya yang
digunakan di [Face ID](https://www.corbado.com/faq/is-face-id-passkey), Touch ID, atau
[Windows Hello](https://www.corbado.com/glossary/windows-hello)). Meskipun biasanya dilakukan secara manual
karena sifat kompleks mengintegrasikan perangkat dunia nyata ke dalam pengujian otomatis,
dimungkinkan untuk mengembangkan skrip automasi kustom. Skrip ini dapat menjembatani
authenticator nyata dengan kerangka kerja pengujian end-to-end, menawarkan perkiraan yang
lebih dekat dengan skenario pengguna nyata dan meningkatkan keandalan proses autentikasi
di lingkungan langsung.

## 8. Rekomendasi untuk Developer

Setelah mendemonstrasikan berbagai opsi dan menampilkan cuplikan kode spesifik untuk
pengujian E2E passkey / WebAuthn dengan Playwright, kami juga ingin memberikan beberapa
rekomendasi yang lebih umum untuk developer yang baru mengenal topik ini.

### 8.1. Pelajari Lanskap Kerangka Kerja Pengujian E2E

Sebelum terjun ke pengujian passkey atau mekanisme autentikasi lainnya, penting untuk
menilai kerangka kerja pengujian E2E yang tersedia dan memilih opsi yang paling sesuai
dengan kebutuhan proyek Anda. Pertimbangkan trade-off antara kecepatan dan stabilitas yang
ditawarkan oleh kerangka kerja berbasis CDP seperti Playwright dan Puppeteer, dan
kompatibilitas lintas-browser yang disediakan oleh kerangka kerja berbasis WebDriver
seperti Selenium dan Nightwatch. Meskipun kerangka kerja berbasis CDP menawarkan automasi
browser yang lebih cepat dan lebih stabil, mereka terbatas pada browser berbasis Chromium.
Sebaliknya, kerangka kerja berbasis WebDriver menyediakan kompatibilitas lintas-browser
yang lebih luas, termasuk dukungan untuk browser non-Chromium seperti Firefox dan Safari,
meskipun dengan kinerja yang berpotensi lebih lambat dan kurang stabil. Memahami trade-off
ini akan membantu Anda membuat keputusan yang tepat dan memilih kerangka kerja yang paling
sesuai dengan kebutuhan proyek Anda.

### 8.2. Pahami Konsep Dasar di Balik WebAuthn dan Passkey

Meskipun WebAuthn virtual authenticator menyederhanakan proses pengujian implementasi
passkey, sangat penting bagi developer untuk memiliki pemahaman yang kuat tentang konsep
dasar di balik standar WebAuthn dan passkey. Biasakan diri Anda dengan berbagai
konfigurasi yang tersedia untuk WebAuthn virtual authenticator, seperti protocol,
transport, hasResidentKey, hasUserVerification, dan isUserVerified. Memahami konfigurasi
ini akan memungkinkan Anda untuk menyempurnakan virtual authenticator untuk mensimulasikan
berbagai skenario autentikasi secara akurat. Selain itu, selami seluk-beluk autentikasi
passkey, termasuk integrasinya dengan berbagai browser dan perangkat, serta pertimbangan
keamanan yang potensial. Pengetahuan dasar ini akan memberdayakan Anda untuk merancang
strategi pengujian yang komprehensif dan efektif untuk autentikasi passkey di aplikasi web
Anda.

## 9. Ringkasan

Panduan ini membahas penggunaan WebAuthn virtual authenticator CDP dengan Playwright,
menyoroti konsep-konsep lanjutan dan mengatasi masalah yang tidak tercakup dalam
dokumentasi resmi. Kami juga menjelajahi alternatif untuk CDP dalam Playwright dan
kerangka kerja pengujian E2E lainnya. Meskipun implementasinya bervariasi, spesifikasi
WebAuthn virtual authenticator yang terstandarisasi memastikan relevansi panduan ini di
berbagai protokol automasi web dan kerangka kerja pengujian end-to-end. Untuk mempelajari
lebih dalam tentang berbagai konsep mengenai passkey, rujuk ke glosarium kami tentang
terminologi relevan yang mungkin membantu Anda menyempurnakan WebAuthn virtual
authenticator berdasarkan kebutuhan Anda.
