# Testing

Once the
[Virtual Cards APIs](https://developers.google.com/pay/virtual-cards-v1/reference/vcn-sequence-diagrams)
have been implemented, it's time to test them. Google provides
[test cases](https://developers.google.com/pay/virtual-cards-v1/guides/testing-and-launch/testing#test_cases)
that may aid you in this process.

## Test cases

This section outlines the test cases expected to be executed to validate your
Virtual Cards APIs implementation.

### Outbound tests

Outbound tests refer to flow direction **Google -\> Integrator**.

#### Common (applies to all outbound endpoints)

1. Invalid encryption returns `invalidPayloadEncryption`
2. Invalid signature returns `invalidPayloadSignature`
3. Invalid JSON returns `invalidDecryptedRequest`
4. Timestamp not within +/- 60 seconds returns `requestTimestampOutOfRange` (this requirement helps protect against replay attacks)
5. RequestId missing returns `missingRequiredField`
6. Invalid [PIAID (paymentIntegratorAccountId)](https://developers.google.com/pay/virtual-cards-v1/reference/glossary#payment_integrator_account_id) returns `invalidIdentifier`

#### Echo

1. Happy Path (clientMessage is echoed in response)

#### Enroll

1. Happy Path
2. PAN is not found returns `unknownPan` decline
3. PAN is recognized but is no longer valid returns `panNoLongerValid`
4. PAN is recognized but the card account has been closed returns `cardAccountClosed`
5. PAN is not eligible returns `cardIneligible` decline
6. PAN invalid format returns `invalidFieldValue` error
7. Expiration date mismatch returns `incorrectExpiration` decline
8. Red-path PAN\* returns `riskDeclined` decline
9. Externally-managed terms of service not accepted by user returns `tosNotAccepted` decline
10. Externally-managed terms of service acceptance timestamp out of date returns `tosAcceptanceOutdated` decline
11. Idempotency - Same `requestId` + same PAN returns `success`
12. Idempotency - Same `requestId` + different PAN returns `idempotencyViolation`
13. Different `requestId` + same PAN returns `success` (2nd enrollment)
    - This can happen if the same PAN is registered by multiple users (different `hashedEmailAddress`) or a single user (same `hashedEmailAddress`) with [multiple payment profiles](https://support.google.com/googlepay/answer/7644003?visit_id=638253754129670000-3896145703&rd=2#multiple-profiles)

#### RetrieveVirtualCardNumber

1. Green path\* returns success
2. Yellow path\* returns `challengeRequired` decline
3. Yellow path\* (including valid challenge result) returns success
4. Yellow path\* (including INVALID challenge result) returns `challengeResultInvalid` decline
5. Yellow path\* (too many\*\* attempts at challenge result) returns `challengeResultVerificationLimitExceeded` decline
6. Yellow path\* (including expired\*\* OTP challenge result) returns `challengeResultExpired` decline
7. Yellow path\* (including expired\*\* challenge option) returns `challengeResultExpired` decline
   - for example if the send OTP limit is 3, OTP timeout is 10 min, and the challenge option timeout is 15 min, the user could timeout the first OTP at 10 min but then timeout the whole challenge at 15 min
8. Red path\* returns `riskDeclined`
9. Idempotency - Same `requestId` + same contents returns same response
   - Green path returns `success`
   - Yellow path returns `challengeRequired` decline
   - Yellow path (including valid challenge result) returns `success`
10. Idempotency - Same `requestId` + different contents returns `idempotencyViolation`
11. `enrollmentRequestId` not found returns `invalidIdentifier` error
12. `enrollmentRequestId` that has been unenrolled returns `invalidIdentifier` error

#### SendOTP

1. Happy Path
2. Expired\*\* challenge option returns `challengeOptionExpired` decline
3. Too many\*\* sendOtps returns `sendLimitExceeded` decline
4. `enrollmentRequestId` has been unenrolled returns `challengeOptionExpired`
   - for example, if (1) `retrieveVirtualCardNumber` returns `challengeRequired`, (2) the card is unenrolled in virtual cards, and then (3) `sendOtp` is called.
5. `challengeOptionId` not found returns `invalidIdentifier` error
6. Idempotency - Same `requestId` + same contents returns same response
   - Does not cause `sendLimitExceeded` for multiple retries (send count only incremented once)
   - Does not resend SMS OTP if it was already sent
   - Does not change expiration result (example w/ 30 min expiration timer: first attempt at 29 minutes, retry (same request ID) at 31 minutes. It should return the same result from the first attempt, not `challengeOptionExpired`)
7. Idempotency - same `requestId` + different contents returns `idempotencyViolation`
8. `enrollmentRequestId` not found returns `invalidIdentifier` error

#### GetTransactions

1. `getTransactions` without `transactionListContinuationToken` returns all transactions for the maximum period prior to the request
2. `getTransactions` with `transactionListContinuationToken` returns all transactions added or updated since the request represented by the token
3. `transactionListContinuationToken` not found returns `unknownTransactionListContinuationToken` (not an `ErrorResponse` with `invalidIdentifier` like other APIs)
4. Idempotency - Same `requestId` + same contents returns same transaction list and `transactionListContinuationToken` in response
5. Idempotency - Same `requestId` + different contents returns `idempotencyViolation`
6. `enrollmentRequestId` not found returns `unknownEnrollment` (not an `ErrorResponse` with `invalidIdentifier` like other APIs)

#### Unenroll

1. Happy Path
2. Idempotency - `enrollmentRequestId` that has already been unenrolled returns success

> [!NOTE]
> **Note:** \* Sandbox PANs can be mapped to certain **Enroll** and **Retrieve** behaviors by the Integrator: **Enroll** : green (always success), red (always risk decline), card ineligible. There is no yellow path. **Retrieve**: green (always success), yellow (always challenge), red (always risk decline). For yellow path, IDV options can be configured, for instance SMS OTP only, or SMS OTP + CVV2.

> [!NOTE]
> **Note:** \*\* Challenge retry or verification limit, send OTP limit, OTP expiration time, and challenge option expiration time are defined by the Integrator.

### Inbound tests

Inbound tests refer to flow direction **Integrator -\> Google**.

#### TransactionEventNotification

1. Happy Path