# Testing

> Produce every outcome on Test: a purchase, a decline, a renewal that fails, a refund, a dispute, a refused build.

Everything on Test runs against Stripe's test mode. Nothing is charged, and every outcome a buyer can meet can be produced with a test card or from the dashboard.

## Before you begin

* A tool wired to Test, with a plan under Pricing. See [Quickstart](https://toolaby.app/docs/quickstart.md).
* For webhooks: an endpoint, or `npx -y toolaby@latest webhooks trigger`. See [Webhooks](https://toolaby.app/docs/reference/webhooks.md#testing-locally).
* For several test buyers from one inbox, `+tag` addresses: `you+1@gmail.com`, `you+2@gmail.com`. Each is a buyer of its own, but they share the inbox's one trial per tool, its free uses where the tool requires an account, and its 20 sign-in links an hour. Dots in a Gmail address are the same buyer.
* On Test, a licence key is mailed only to a member's own address, or on Gmail one of its `+tag` addresses. A key bought for any other address is made and not mailed, and the page after the purchase says so. A seat given to such an address is given, without its mail.

## Cards

On Stripe's checkout page, any future expiry date and any CVC.

| Card                  | Outcome                                                                                   |
| --------------------- | ----------------------------------------------------------------------------------------- |
| `4242 4242 4242 4242` | Paid.                                                                                     |
| `4000 0000 0000 0002` | Declined. Stripe shows the decline; nothing is recorded.                                  |
| `4000 0025 0000 3155` | Requires 3D Secure authentication first.                                                  |
| `4000 0000 0000 0341` | Attaches to the customer, then fails when charged: after a trial, the first charge fails. |
| `4000 0000 0000 0259` | Paid, then disputed: `payment.disputed` follows within minutes.                           |
| `4000 0000 0000 9995` | Insufficient funds.                                                                       |

Stripe's full list is at [docs.stripe.com/testing](https://docs.stripe.com/testing).

## Scenarios

| To see                       | Do                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| A purchase                   | Buy from the popup with `4242…`. The popup unlocks; the customer appears; `purchase.completed` is sent.                                                                                                                                                                                                                                                                                                                            |
| A subscription with a trial  | Set a free trial on the subscription plan under Pricing, subscribe. Stripe's page says *n days free*; `user.subscription.status` is `trialing`.                                                                                                                                                                                                                                                                                    |
| A failed renewal             | Give the subscription plan a 1-day free trial under Pricing, set **Access** to *Nothing free*, and subscribe with `4000 0000 0000 0341`, from an inbox that has not had the tool's trial. When the trial ends, the charge fails and the subscription is `past_due`, which unlocks nothing: `gate()` refuses with `paid`, and the Toolaby popup says *Payment failed — update your card*. See [Subscriptions](https://toolaby.app/docs/subscriptions.md). |
| A cancellation               | **Cancel** on the customer's page, or the buyer's account page (Stripe's portal). `subscription.cancelled` is sent: see [Subscriptions](https://toolaby.app/docs/subscriptions.md#5-set-to-end).                                                                                                                                                                                                                                                         |
| A plan switch                | From the buyer's account page, **Change plan**. The row updates within seconds.                                                                                                                                                                                                                                                                                                                                                    |
| A refund                     | **Refund** on the customer's page. The licence is revoked; the extension stops at its next check; `payment.refunded` is sent.                                                                                                                                                                                                                                                                                                      |
| A dispute                    | Pay with `4000 0000 0000 0259`. The licence shows as disputed; `payment.disputed` is sent. In test mode a dispute closes when evidence is submitted on it: the text `winning_evidence` wins it, `losing_evidence` loses it, and `dispute.closed` follows. Evidence is submitted from the account's Stripe Dashboard, which the Test account Toolaby makes does not have: on Test the dispute stays open.                           |
| A refused build              | Under Versions, set a minimum version above the extension's. The Toolaby popup shows your message at its next open. Without an open, `gate()` refuses within the hour.                                                                                                                                                                                                                                                             |
| The Free plan's limit        | Set **Pricing → Access** to *Free uses*, and use them up. The paywall appears with the plans.                                                                                                                                                                                                                                                                                                                                      |
| A second device              | Load the extension in a second Chrome profile and sign in. The account page lists both. A third beyond *Devices per licence* is refused.                                                                                                                                                                                                                                                                                           |
| A grant                      | **Grant access** on a customer's page, for an address that has signed in or that you added with **Create customer** on the **Customers** page. Or `POST /tools/{tool}/grants`, which makes the account itself. The extension unlocks at its next check.                                                                                                                                                                            |
| Another language or currency | See [Buyer pages](https://toolaby.app/docs/buyer-pages.md#languages).                                                                                                                                                                                                                                                                                                                                                                                    |

## Webhooks without a purchase

```bash
npx -y toolaby@latest webhooks trigger payment.refunded --to http://localhost:4000/webhooks
```

Sends the event's example, signed, to a server on your machine. See [Webhooks](https://toolaby.app/docs/reference/webhooks.md#testing-locally).

## Resetting

There is no reset. Delete the test tool under its Settings, or refund and revoke from the Customers page. Buyers on Test are separate from live and are never copied there.
