First of all, welcome to Test-Driven Laravel!
To get things started, let's talk a bit about the app we are going to build, and figure out where we should start.
2. Sketching out Our First Test
In this lesson, we scaffold out a new application and start sketching out the first test.
We start the course with Laravel 5.3 which was the current version at the time of recording. If you want to follow along line-by-line, I recommend that you start with a fresh 5.3 project, and upgrade to 5.4 and beyond when we do it in the course.
To create a fresh Laravel 5.3 project, run this in your terminal:
composer create-project laravel/laravel=5.3.* ticketbeast
If you'd like to start with Laravel 5.4 (or even 5.5), I recommend watching the upgrade videos first so you have an idea of what differences you need to watch out for.
In this lesson, we use TDD to scaffold out a lot of the boiler plate in the application and get our first test passing.
4. Unit Testing Presentation Logic
In this lesson, we drive out some presentation helpers via unit tests to extract some logic from our view.
In this lesson, we finish extracting some presentation helpers, then refactor our tests to run without using the database to keep things fast.
6. Hiding Unpublished Concerts
In this lesson, we introduce the idea of "published" and "unpublished" concerts, and hide unpublished concerts from visitors to the site.
In this lesson, we extract some query logic to a custom scope and ensure that it's covered by our tests.
In this lesson, we abstract some details about makes a concert "published" from our tests by encapsulating them in a factory state.
In this lesson, we talk about getting started with the "Purchasing Concert Tickets" feature that we're going to implement next.
10. Browser Testing vs Endpoint Testing
In this lesson, we talk about the trade-offs involved in testing through the browser vs. testing an endpoint directly, and why you might choose one option over the other.
11. Outlining the First Purchasing Test
In this lesson, we design our initial "customer can purchase concert tickets" test.
12. Faking the Payment Gateway
In this lesson, we create a fake implementation of our payment gateway to avoid hitting Stripe during our integration tests.
In this lesson, we work on creating tickets and attaching them to orders when a customer makes a purchase.
14. Encapsulating Relationship Logic in the Model
In this lesson, we work on refactoring some of our controller code and pushing some logic into the model.
15. Getting Started with Validation Testing
In this lesson, we work on testing and implementing some request validation rules.
16. Reducing Duplication with Custom Assertions
In this lesson, we abstract some commonly paired assertions behind a custom assertion with a more expressive name.
In this lesson, we drive out what should happen when a customer's payment fails.
18. Preventing Ticket Sales to Unpublished Concerts
In this lesson, we add a new feature test to cover the situation when someone tries to view a concert that hasn't been published yet.
19. Outlining the First Test Case
In this lesson, we work on writing a test to ensure that customers can't purchase more tickets than are still available.
20. Adding Tickets to Concerts
In this lesson, we implement the ability to add tickets to concerts so there are tickets available when a customer tries to purchase.
21. Refusing Orders When There Are No More Tickets
In this lesson, we work on making sure orders are not created when someone tries to purchase more tickets than remain, and ensuring that a customer can't purchase tickets already purchased by another customer.
22. Finishing the Feature Test
In this lesson, we get our "cannot purchase more tickets than remain" feature test passing by finishing our controller implementation.
In this lesson, we make sure that if a customer's payment fails, we cancel their order.
24. Refactoring and Redundant Test Coverage
In this lesson, we extract some logic from our Order class to our Ticket class, and discuss whether or not it's important to add new test coverage.
Much like production code, test code needs to be refactored and kept healthy and maintainable.
In this lesson, we go over our existing test suite and look for opportunities to clean it up.
26. Asserting Against JSON Responses
In this lesson, we add tests to ensure that we are getting back meaningful order information after purchasing tickets, and discuss different strategies for testing JSON responses.
In this lesson, we work on getting our existing feature test passing by driving out an order's JSON representation at the unit level.
You don't always write beautiful code on the first try.
In this lesson, we talk about three issues with our existing design and why they are worth addressing.
29. Persisting the Order Amount
In this lesson, we work on persisting the order amount to the database, instead of calculating it on the fly based on ticket price and ticket quantity.
30. Removing the Need to Cancel Orders
In this lesson, we work getting rid of the need to cancel orders when a payment fails by separating the idea of finding tickets from confirming an order.
In this lesson, we work on removing the need to create orders through a concert by removing a redundant relationship.
32. Extracting a Named Constructor
In this lesson, we introduce a named constructor for creating orders from customer details and tickets.
33. Precomputing the Order Amount
In this lesson, we work on removing the need for an order to know how to calculate it's own price so we can eliminate some duplication in our code.
34. Uncovering a New Domain Object
In this lesson, we walk through a strategy I use to discover new objects in my code, and start driving out a new domain object with tests.
35. You Might Not Need a Mocking Framework
In this lesson, we work on removing the need to migrate the database when testing our simple Reservation class.
We also talk about different approaches to isolating the Reservation from it's collaborators, and why you might not need a special library to do it.
Over the last few lessons we've improved the design of our code significantly, but we've also introduced a race condition.
In this lesson, we discuss how subrequests work, and how we can use them to help test this race condition.
In this lesson, we add a hook to our fake payment gateway to allow us to trigger a nested request.
In this lesson, we finish writing our feature test to cover the race condition. But when we run it, we hit a segfault! Let's see if we can diagnose the issue.
40. Replicating the Failure at the Unit Level
In order to get a better understanding of our segfault issue, we try and replicate it at the unit level so we can fix it more easily.
41. Reserving Individual Tickets
To make sure nobody can purchase someone else's tickets while they are still trying to pay, we work on introducing the idea of a ticket being "reserved."
It this lesson, we work on making sure the rest of the application respects our newly introduced "reserved" status on tickets.
43. That Guy Stole My Tickets!
For some reason, person B is getting their name added to tickets that person A paid for! Let's figure out what's going on.
In this lesson, we find a sneaky bug and work towards solving it through an isolated unit test.
45. Refactoring Mocks to Spies
In this lesson, we talk about 3 different ways to create mock objects, as well as how using spies instead of mocks can help keep your tests more organized.
Our feature test is still failing because some of our older code has a different understanding of what it means to "release" tickets.
In this lesson, we diagnose the issue and update our specification to help us drive out the change in behavior.
In this lesson we discuss the importance of high level feature tests, and how they help give us the confidence to delete stale code when confronted with a failing unit test.
48. Cleaning up a Loose Variable
In this lesson, we look to eliminate a loose variable in our controller by adding some additional behavior to our Reservation class, and then spend some time pushing the responsibility for creating reservations inside our Concert class and our of our controller.
49. Moving the Email to the Reservation
In this lesson, we notice a long parameter list we'd like to refactor, but in order to do that, we need to tweak how reservations are created so that the reservation has knowledge of the customer who is reserving the tickets.
50. Refactoring "Long Parameter List" Using "Preserve Whole Object"
In this lesson, we attempt to refactor the "long parameter list" code smell we noticed in our Order class using the "preserve whole object" refactoring.
Our "preserve whole object" refactoring didn't turn out as nicely as we hoped.
In this lesson, we look to treat the original problem as a "feature envy" issue instead of a "long parameter list" issue, and see if that leads us to a better solution.
52. Avoiding Service Classes with Method Injection
In this lesson, we notice that we're lacking a single source of truth for the amount we charge the customer and the amount used to create the new order.
We walk through what it might look like to solve this problem with a service class, and then how we can avoid the service class entirely using method injection.
53. Generating a Valid Payment Token
In this lesson we scaffold out an initial test for our StripePaymentGateway and figure out how to generate a valid payment token using Stripe's API.
54. Retrieving the Last Charge
In this lesson we use Stripe's API to fetch the most recent charge so we can make assertions about it in our test.
55. Making a Successful Charge
In this lesson we work through the first set of test failures and successfully make a charge to Stripe.
56. Dealing with Lingering State
In this lesson we diagnose why are test is passing after commenting out our implementation, and come up with a new strategy to run our tests with isolated data.
Two small corrections were made to the code in the video before committing:
array_firstIn the lastCharge method, we were trying to access the element at offset 0 to get the most recent charge:
private function lastCharge()
{
return \Stripe\Charge::all(
['limit' => 1],
['api_key' => config('services.stripe.secret')]
)[data][0];
}
This will throw an error if you don't happen to have any charges created yet.
Instead, use array_first to get the first charge or null if no charges are present:
private function lastCharge()
{
return array_first(\Stripe\Charge::all(
['limit' => 1],
['api_key' => config('services.stripe.secret')]
)['data']);
}
The newCharges method was also updated to check for null before trying to get the id of the last charge:
private function newCharges()
{
return \Stripe\Charge::all(
[
'limit' => 1,
'ending_before' => $this->lastCharge ? $this->lastCharge->id : null,
],
['api_key' => config('services.stripe.secret')]
)['data'];
}
When copying over the newCharges implementation, we mistakenly left in the limit parameter:
private function newCharges()
{
return \Stripe\Charge::all(
[
'limit' => 1,
'ending_before' => $this->lastCharge ? $this->lastCharge->id : null,
],
['api_key' => config('services.stripe.secret')]
)['data'];
}
This was removed before committing to make sure we always get all the charges back that were created in the test, and not just the most recent one:
private function newCharges()
{
return \Stripe\Charge::all(
[
'ending_before' => $this->lastCharge ? $this->lastCharge->id : null,
],
['api_key' => config('services.stripe.secret')]
)['data'];
}
57. Don't Mock What You Don't Own
A common misconception about testing is that you should mock calls to external APIs to avoid the network.
In this lesson, we compare the pros and cons of integrating with Stripe vs. mocking our calls to Stripe to better understand why shouldn't mock third-party code.
58. Using Groups to Skip Integration Tests
In this lesson, we use PHPUnit's "group" feature to make it easy to skip our integration tests when we don't have an internet connection.
59. Handling Invalid Payment Tokens
In this lesson we add a new test to make sure our StripePaymentGateway behaves as expected when attemping to charge with an invalid payment token.
In this lesson, we finally fire up the browser to find out if all of this TDD stuff has really given us a working system.
61. When Interfaces Aren't Enough
In this lesson, we identify some of the risks of using fakes, and why it takes more than an interface to make sure multiple implementations stay in sync.
62. Refactoring Towards Duplication
In this lesson, we begin refactoring the tests for our two PaymentGateway implementations towards being identical so we can extract them to a contract test.
63. Capturing Charges with Callbacks
In this lesson, we come up with a strategy for being able to keep track of the total charges made during a test that will work for both implementations of our PaymentGateway interface.
64. Making the Tests Identical
In this lesson, we port the newChargesDuring method over to the FakePaymentGateways, finally leaving us with two identical tests that are ready for extraction.
65. Extracting a Contract Test
In this lesson, we extract the identical PaymentGateway tests into a contract test, shared through a trait.
66. Extracting the Failure Case
In this lesson, we refactor the charges_with_an_invalid_payment_token_fail tests to make them identical, and then extract it to our contract test.
In this lesson, we upgrade TicketBeast to Laravel 5.4, and get our tests back to green using the browser-kit-testing package.
68. Removing the BrowserKit Dependency
In this lesson, we refactor our BrowserKit tests to use Laravel 5.4's testing features, so we can remove our dependency on the compatibility package.
69. Sketching out Order Confirmations
In this lesson, we begin driving out our test for viewing order confirmations based on a static mockup.
In this lesson, we figure out the URL structure we want to use to keep order confirmation pages private, and drive out the ability to successfully hit out new endpoint.
71. Asserting Against View Data
In this lesson, we flesh out an initial implementation of our controller, and walk through how to test the data that is bound to a view without asserting against the rendered HTML.
72. Extracting a Finder Method
In this lesson, we refactor some Eloquent calls in our controller to a dedicated finder method, and discuss when it's important to add new tests while refactoring and when it's not.
In this lesson, we work through using tests to replace some of the hard coded data in our mockup with real data that's attached to our order.
74. Deciding What to Test in a View
In this lesson, we spend some time discussing what you need to take into consideration when deciding what data is important to test in a rendered view.
75. Decoupling Data from Presentation
In this lesson, we talk about strategies you can use to make your feature tests more resilient to superficial changes in your templates, and work through a specific example using dates.
In this lesson, we get our test suite back to green by temporarily making some of our new columns nullable, and discuss adding a test to ensure confirmation numbers are generated for new orders.
In this lesson, we decide we want to be able to stub how order confirmation numbers are generated for our high level feature test, and use that insight to design an interface where we can encapsulate that logic.
In this lesson, we update one of our Order unit tests to make use of the factory we added previously, and make sure that orders include their confirmation numbers when we render them as JSON.
79. Confirmation Number Characteristics
In this lesson, we discuss the what we want our confirmation numbers to ultimately look like and why.
80. Testing the Confirmation Number Format
In this lesson, we use the characteristics we identified previously to specify how our confirmation numbers should look with a set of unit tests, and work on getting them to pass.
In this lesson, we come up with a strategy to force ourselves away from our slimed implementation by testing that each confirmation number is unique.
In this lesson, we wire up our RandomOrderConfirmationNumberGenerator to be the default implementation we use in our application, and make use of Laravel's Facades to replace our explicit use of Laravel's container in our Order class with something more expressive.
83. Promoting Charges to Objects
In this lesson, we introduce a new Charge object to carry meta data about purchases, such as the last four digits of the card used. We drive out this change in our FakePaymentGateway first through changes to our PaymentGatewayContractTests.
84. Leveraging Our Contract Tests
In this lesson, we use our updated contract tests to update the behavior of our StripePaymentGateway to keep it synchronized with our fake.
85. Storing Charge Details with Orders
In this lesson, we update our OrderTest to account for creating orders using Charges instead of plain amounts, and use that test to drive out the implementation in Order.
In this lesson, we notice that changing how Orders are created reveals some lingering old design decisions that are triggering test failures. We work through removing the stale code, and updating any tests we need to keep to no longer rely on the code we want to remove.
87. Feature Test and JSON Updates
In this lesson, we come up with approach for driving out the generation of ticket codes from the outside in, and make some tweaks to the JSON representation of a completed order.
88. Claiming Tickets When Creating Orders
In this lesson, we decide when ticket codes should be generated, and rework an existing test to use mock expectations to prepare for our implementation.
89. Assigning Codes When Claiming Tickets
In this lesson, we add a new test for the new claimFor method in our Ticket class, and drive out the implementation.
In this lesson, we talk about the birthday problem and the implications it has on how we generate ticket codes.
We also play with the Hashids library to get an understanding of how we could use it to encode ticket IDs.
In this lesson, we drive out our HashidsTicketCodeGenerator, making sure that ticket codes are generated in the format we expect.
92. Dealing with Out of Sync Mocks
Uh oh! One of our mock expectations is no longer in sync with the real implementation.
In this lesson, we use an underappreciated Mockery feature to detect broken mocks, and get things working properly again.
In this lesson, we bubble back up to our initial feature test and try to get it passing.
We cover how to return multiple values from a Mockery stub, and wire up our real HashidsTicketCodeGenerator in the IOC container to get the test suite back to green.
In this short lesson, we make a small tweak to our TicketCheckout Vue component and finally walk through the entire purchasing flow from start to finish.
95. Using a Fake to Intercept Email
In this lesson, we use Laravel's Mail Fake to test sending an order confirmation email whenever someone purchases tickets.
In this lesson, we come up with a way to render mailables as HTML so we can assert against their contents.
In this lesson, we configure Mailtrap so we can test our order confirmation email flow in the browser.
98. Testing the Login Endpoint
The next thing we'd like to build is the ability for promoters to add new concerts, but before we can do that, we need to give them a way to log in to the application.
In this lesson, we drive out our initial /login endpoint.
99. Should You TDD Simple Templates?
In the last lesson we drove out the login endpoint, but we still don't have an actual login form.
Is this something we should try to build with TDD, or is there a better approach?
100. Namespacing Our Test Suite
Before we get started with Laravel Dusk, let's update our test folder structure to match what ships with Laravel 5.4 to make it a little easier to integrate.
101. Getting Started with Laravel Dusk
In this lesson, we install and configure Laravel Dusk, talk about some gotchas you might run into if you're not approaching it with the right mindset, and get a basic example browser test running.
We're using Laravel Dusk ^1.1 in this video and ^2.0 doesn't support Laravel 5.4, so if you're following along in 5.4, you'll want to install ^1.1 explicitly:
composer require laravel/dusk:^1.1
102. QA Testing the Login Flow
In this lesson, we use Dusk to drive out a browser test for our login form to make sure we have regression coverage.
103. Preventing Guests from Adding Concerts
In this lesson, we walk through some behind-the-scenes changes made since the last lesson and work on adding some basic authorization tests.
In this lesson we drive out the ability to add new concerts and make sure only promoters can access this endpoint.
In this lesson we drive out our first validation rule for the concert form, and look at a useful trick for making assertions about redirect()->back() behavior.
In Laravel v5.5.19, the custom from helper we added in this lesson was added natively, so it's not necessary to add it yourself as long as you upgrade to the latest version of Laravel.
106. Converting Empty Strings to Null
In this lesson we add a test to prove that concert subtitles are optional, and active some new middleware from Laravel 5.4 to simplify the task.
107. Reducing Noise with Form Factories
In this lesson we identify a lot of duplication in our validation tests and use a technique similar to model factories to clean up the noise.
108. Connecting Promoters to Concerts
Up until now we've been operating under the assumption that we'd add concerts manually on a promoter's behalf.
Now that promoters can add concerts themselves, we need to make sure we are tracking who adds each concert so we know who to transfer the ticket money to.
109. Autopublishing New Concerts
In one of the earliest lessons in the course, we added some functionality to make sure that only published concerts were visible in the browser.
Since we don't have the ability to publish new concerts from the UI yet, let's at least make sure that new concerts are published by default until we get to that feature.
110. Asserting Against View Objects
In this lesson we start driving out tests for a concert index page. We also talk about an incredibly useful strategy for making assertions about views without dealing with HTML.
111. Avoiding Sort-Sensitive Tests
In this lesson I outline a small sort-order related trap you can fall into if you're not careful when asserting against lists of items, and talk about a strategy for avoiding it.
112. Refactoring Assertions with Macros
In this lesson we work through using Laravel's macro feature to create more expressive custom assertions.
In this lesson, I walk through some simple tests I put together behind-the-scenes to give us a head start on updating concerts.
If you're building along in your own repo, be sure to go through the changes made in this lesson's commit and apply them to your own project.
Most notably, we've moved the $response->data(...) macro to the base TestCase class so we can reuse it in our other tests.
In this lesson, we drive out the first test we need for editing concert details, and talk through a useful naming strategy to use when testing for attribute changes.
115. Driving Out Basic Concert Updates
In this lesson we implement the ability perform concert updates, and start working through some of the permission checks we need to be concerned with.
116. Restricting Updates to Unpublished Concerts
In this lesson we make sure only unpublished concerts can be edited, prevent guests from editing concerts, and drive out an example validation rule.
In Laravel v5.5.19, the custom from helper we've been using in our tests was added natively, so rather than moving it to the base test case, feel free to run composer update to pull in the latest version of Laravel and delete that helper entirely.
117. Storing the Intended Ticket Quantity
In this lesson we figure out how to deal with updating the ticket quantity by deciding to delay ticket creation until publishing.
In this lesson we walk through some local test failures caused by our design change and get things back to green.
119. Refactoring Away Some Test Duplication
In this lesson we remove some repetitive setup and assertions by introducing a new test helper.
120. Creating Tickets at Time of Publish
In this lesson we drive out the ability to create tickets at time of publish through our Concert unit tests, all while keeping our feature tests passing.
In this lesson we extract some repetitive complex factory setup into a custom ConcertFactory class.
122. Discovering a New Resource
In this lesson we talk about three different approaches for exposing the ability to publish concerts through our applications endpoints.
Here are the direct links to the commits that were made behind the scenes:
123. Creating Published Concerts
In this lesson we drive out the ability to publish concerts through our new /published-concerts resource.
124. Adding Concerts without Publishing
In this lesson we update our existing "add concert" flow to not publish concerts immediately.
Here's a link to the work that was done between this lesson and the previous one:
125. Pushing Logic Out of the View
Our template is doing a little bit too much work. Let's figure out a way to extract some of that logic into a place that's easier to test.
126. More Custom Assertion Fun
Some of our assertions are looking a little bit overwhelming. Let's create a new custom assertion to make our test a bit more expressive.
In this lesson walk through a few behind-the-scenes changes, then drive out a method for calculating tickets sold.
128. Making the Progress Bar Work
In this lesson we add some new methods for calculating the percentage of tickets sold, and touch on a neat tip for making assertions about floating point numbers.
129. Total Revenue and a Relationship Bug
In this lesson we work on calculating the total revenue for a concert, but run into an interesting bug we need to tackle with our $concert->orders relationship.
130. Creating a Custom OrderFactory
In this lesson we start working on making it possible for promoters to view a list of recent orders. When we hit a snag with some complex factory setup, we work on extracting a custom factory class to simplify our code.
131. Asserting Against Sort Order
In this lesson we add the assertions we need to verify that our recent orders are getting passed to the view in the right order, and discuss why asserting against view data makes this so much easier than it would be if we were asserting against HTML.
In this lesson we talk about when, why, and how to split up a large test into many.
133. Storing Messages for Attendees
In this lesson we add the ability to create a new message to be sent to all concert attendees.
Here's a direct link to the work done behind the scenes:
View "(add template and routing for message attendees form)" commit on GitHub
134. Confirming That a Job Was Dispatched
In this lesson, we update our "store attendee message" implementation to actually dispatch a background job for sending the message.
Here's a link to a commit made after this lesson, where authorization and validation tests were added:
View "(add authorization and validation tests)" commit on GitHub
In this lesson we drive out the implementation of the actual background job via a dedicated unit test.
136. Refactoring for Robustness
In this lesson we refactor the implementation of our background job to better handle large numbers of recipients.
137. Mailable Testing Refresher and Demo
In this lesson we walk through a unit test for our new mailable and demo our new mass email feature.
Here's a link to a commit made behind the scenes to make some updates to our form template:
In this lesson we use our test suite to guide us as we upgrade to Laravel 5.5.
139. Faking Uploads and File Systems
In this lesson we write our first test for uploading concert images, and walk through how to attach files to requests in feature tests, as well as how to use Laravel's built-in file system fake to make assertions about file uploads.
140. Storing Files and Comparing Content
In this lesson we get our initial file upload test passing, and also talk about how to verify that the stored file contents match the uploaded file contents.
In this lesson we add additional tests for validating the file type, dimensions, and aspect ratio of uploaded concert posters.
142. Optional Files and the Null Object Pattern
In this lesson we add a test to make sure that concert posters are optional, and come up with a clean implementation using the Null Object pattern.
In this lesson we decide on a design for our poster image processing feature and start by test-driving an event.
Here's a direct link to the work done behind the scenes:
144. Testing the Event Listener
In this lesson we drive out our SchedulePosterImageProcessing event listener with TDD.
145. Resizing the Poster Image
In this lesson we walk through how to test resizing images using the Intervention Image image processing library.
146. Optimizing the Image Size
In this lesson we add an additional processing step to reduce the image size, and talk about how to test that the optimized image still looks like the original image.
147. Upgrading Laravel and Deleting Some Code
Before we get started with the next feature, let's quickly upgrade to the latest Laravel patch release and take advantage of some new features that let us delete some of our custom helpers.
148. Viewing an Unused Invitation
In this lesson, we drive out the ability for a promoter to view their invitation to join TicketBeast.
149. Viewing Used or Invalid Invitations
In this lesson, we drive out what should happen when someone tries to view an invitation that has already been used, as well as an invitation that doesn't exist.
150. Registering with a Valid Invitation
In this lesson we drive out the form endpoint for registering with a valid invitation code.
151. Registering with an Invalid Invitation
In this lesson we make sure that users can't register with invalid invitation codes.
152. Validating Promoter Registration
In this lesson we add some validation rules to our registration flow.
153. Testing a Console Command
In this lesson we TDD a custom Artisan command for creating new invitations.
154. Sending Promoters an Invitation Email
In this lesson we enhance our custom command to also send an invitation email to the promoter being invited.
155. Test-Driving the Email Contents
In this lesson we make sure that the invitation email contains the correct invitation link, and run through a quick demo of our now finished feature.
156. Getting Cozy with Stripe Connect
In this lesson, we learn about how Stripe Connect works and drive out an initial test for the OAuth redirect flow using Laravel Dusk.
In this lesson we implement the first half of the Stripe Connect redirect flow, where we send promoters to Stripe to connect their account.
In this lesson we handle the second half of the redirect flow; exchanging the temporary code Stripe gives us for a valid access token that we can use to make requests on behalf of a promoter.
In this lesson we work on driving out a middleware that will force promoters to connect a Stripe account.
160. Testing Callbacks with Invokables
In this lesson we make sure our middleware doesn't block promoters who have already connected their Stripe accounts, covering an approach for testing interfaces that accept callbacks using invokable classes.
161. Testing That Middleware Is Applied
In this lesson we discuss and implement a strategy for making sure that our new middleware is applied to the correct routes.
162. Updating Factories and a Speed Trick
In this lesson we check if our new middleware has had any impact on the rest of our test suite, and walk through a quick trick that can dramatically speed up your test suite.
163. Total Charges for a Specific Account
In this lesson we start working on sending payments directly to promoters by making sure we can verify which accounts received which payments.
164. Paying Promoters Directly
In this lesson we make the necessary changes to our application code to make sure that when a payment is processed it's sent to the promoter's account instead of the application account.
165. Splitting Payments with Stripe
In this lesson we update our StripePaymentGateway to match our new payment gateway contract, and add an additional test to make sure that payments processed by Stripe are split as expected between the application account and the promoter's account.
In the final lesson of Test-Driven Laravel, we do one last demo of the ticket purchasing process from inviting a promoter to receiving an order confirmation, and double check that everything really is working as expected via the Stripe dashboard.