Overview
This PR adds a way for users to easily fake events and API calls with a single command and a couple options for customizing the responses and asserting that certain events are dispatched.
How it works
Under the hood, Cashier::fake()
creates a new instance of CashierFake
which, upon creation, fakes API calls with Http::fake()
and Cashier-provided events as well with Event::fake()
. A user may customize this experience if they wish to override the defaults by providing an array with an endpoint as the key and a response as its value as such:
Cashier::fake([
'subscription/create' => ['fake-response' => 'and its data']
]);
Internally, CashierFake will format this path into a paddle API call within the retrieveEndpoint($path)
call which uses Cashier's vendorsUrl
method and some constants to return an endpoint such as: vendors.paddle.com/api/2.0/subscription/create
. From here it will take the faked response and either return it as part of a Http::response
if it's an array or allow the user to customize that behaviour by passing a function.
There are two additional methods that can be used: paypal()
and card()
. These functions change the information returned by the subscription/users
endpoint with paypal()
sending a response that the user is paying via PayPal and card()
that it is paying through a Visa with the following parameters:
{
card_type: 'visa',
last_four_digits: '1234',
expiry_date: '04/2022',
}
If these values need to be overwritten, you may pass your own information to the card()
method and it will merge this into the response as such:
Cashier::fake()->card(['card_type' => 'mastercard']);
Finally the CashierFake
method also fakes Events provided by the library. These events are:
- Laravel\Paddle\Events\PaymentSucceeded
- Laravel\Paddle\Events\SubscriptionCancelled
- Laravel\Paddle\Events\SubscriptionCreated
- Laravel\Paddle\Events\SubscriptionPaymentFailed
- Laravel\Paddle\Events\SubscriptionPaymentSucceeded
- Laravel\Paddle\Events\SubscriptionUpdated
A user may append additional events to this process if they wish by adding passing them to the fake such as:
Cashier::fake(events: CustomEvent::class);
// or
Cashier::fake(events: [CustomEvent::class, AndAnotherOne::class]);
This also provides a number of assertions, present both on the CashierFake
and Cashier
class. The assertion methods on the Cashier
act as a proxy for the CashierFake
and forward the requests into that class. I went with this approach instead of putting the assertions only on the Cashier
as I felt importing all the events it needed to cover, plus the Event Facade felt messy and distracts a dev who is trying to understand the concerns of the Cashier
class. Open to feedback on this one or if someone wants to recommend a better way of doing this.
Example of assertion syntax:
// Switching between Cashier/CashierFake sucks
Cashier::fake()
CashierFake::assertSubscriptionCreated();
// This looks better:
Cashier::fake();
Cashier::assertSubscriptionCreated();
// However this looks like garbage...so again...placed the assertions in CashierFake and
// did a bit of code duplication in favour of import hell.
use Illuminate\Support\Facades\Http;
use Laravel\Paddle\Exceptions\PaddleException;
use Money\Currencies\ISOCurrencies;
use Money\Currency;
use Money\Formatter\IntlMoneyFormatter;
use Money\Money;
use NumberFormatter;
use Illuminate\Support\Facades\Event;
use Laravel\Paddle\Events\PaymentSucceeded;
use Laravel\Paddle\Events\SubscriptionCancelled;
use Laravel\Paddle\Events\SubscriptionCreated;
use Laravel\Paddle\Events\SubscriptionPaymentFailed;
use Laravel\Paddle\Events\SubscriptionPaymentSucceeded;
use Laravel\Paddle\Events\SubscriptionUpdated;
class Cashier
{
// ...
}
One final thing...
Let me know if you want me to remove this but I found that setting <server />
variables in my PHPUnit did nothing...<env />
did...so I've updated the CONTRIBUTING.md
file with that. I've also added an env there for PADDLE_SANDBOX
because it's likely that you're going to be testing in sandbox mode...not sure if this should also be a part of the phpunit.xml.dist
too...lemme know.