Plan the Feature Test0:00
We have already made sure that we can receive calls from our payment provider, Petal. These calls also get verified, and we also store them inside the database. And also a specific job is being triggered, which is this one here, which is currently empty. Now it's time to fill this job and finally handle our valid purchase. And as always, we're going to start by creating a new test. It will be FeatureTest, and we're going to call it HandlePetalPurchaseJobTest. All right, let's think about what do we want to test here. First, we want to make sure that it stores a Petal purchase. In our case, a purchase is a product connected to a specific User. This is what we refer to as a purchase in our application.
In our case, a Purchase is a Product connected to a specific User. This is what we refer to as a Purchase in our application. Then next, we also want to make sure that if there is already a given User, then we want to use this one. So it stores Petal Purchase for given User. So this means if we don't have a given User, in this case, we want to create a new User, and here we want to use a given User. All right, and last, we also want to make sure that we send out a specific email to the User about the Purchase. It sends out Purchase email.
to the user about the purchase. It sends out purchase email. All right, so this is the plan for this video. We want to make sure that we use our Job in order to store a PetalPurchase. We want to make sure that if there is a given User, we want to use this one, and we also want to make sure that we send out an email to the User about what he or she just bought. All right, so how are we going to test this? I already know that I want to make sure at the end after this test, after this Job, we want to make sure that we have a new User in the database.
Set Up Test Data1:50
I already know that I want to make sure at the end after this test, after this job, we want to make sure that we have a new User in the database and a new entry for a purchased Course. So that's why I like to start here by asserting that those tables are empty. assertDatabaseCount, and first for our User, we want it to be empty like this, and then also for our purchased Course, which is a model of which we already have. So this is the connection between a User and the product and the Course. This also should be empty. Also, by the way, I think the time that you're going to see this video,
This also should be empty. Also, by the way, I think the time that you're going to see this video, there's already a new method which I created for level which you can use, which is going to be called assertDatabaseEmpty like this, and then we don't need to provide this here. But currently, I don't think it's already available because I think it just comes with the next release. So that's why currently we still have to use this. But for you, I think it's good to know. Let's also import the namespaces.
But for you, I think it's good to know. Let's also import the namespaces. All right. Then we need some data inside our application. So what do we need? Of course, we're going to need a course. So let's create a new one, CourseFactory. And what do we need here? I think what's important is that we have a valid productId, and let's just use one from our products.
I think what's important is that we have a valid product ID, and let's just use one from our products. All right. So it's important that we define this here because what we also need to define is a webhook call. So this is a model which we get through the package which we use by Sparcy for handling all the incoming webhook calls, and we need to have an entry for this call because we need to provide it then to our shop. And this is how we connect the webhook call to the right course,
because we need to provide it then to our shop. And this is how we connect the webhook call to the right course, by providing the correct pedal product ID. So let's see whether we have this model. I think it's this one. And here we now also need to create a new one. And there is currently no factory for this model because this model is not created by us. This comes through a package, but I also don't want to create now a factory for a model.
This comes through a package, but I also don't want to create now a factory for a model which I don't own. That's why I'm just using the create method here to create a new webhook call. The only downside here is that we need to fill all the fields here that are required for this model. So we have here a name, and let's just keep this by default. Then what else do we have?
and let's just keep this by default. Then what else do we have? We have an URL, some URL. It's also not what we're going to need to work with. And then very interesting, we're going to have here a payload, which is an array with some important data. So this is what comes through the webhook call. And what we are going to need is the email. Let's use test@test.at for Austria. Then we need a name.
Let's use test at test.at for Austria. Then we need a name. So these are fields that we store inside our database, testUser. And then also what we get is this productId, which is our paddleProductId, which we need in order to connect this webhook call to a specific course of us. So here we now need to use the same ID, 34779. Yeah, I think this looks good. Let's import some namespaces again and move on now to the act part.
Run Job and Assert5:18
Yeah, I think this looks good. Let's import some namespaces again and move on now to the act part. So the good thing about Chops is that you can quite easily just call them by just creating a new ChopHandlePurchaseChop. And then you can just run the handle method on the Chop because the handle method here is the method which you have for all Chops in that level. So this method is always given. But as you can see, there is already a parameter missing for the webhook call.
But as you can see, there is already a parameter missing for the webhook call. And this is what we now need to provide here to the Chop. And let's just provide our webhook call. All right. And then we're going to run the Chop and then we need to make some assertions. So let's start with the User. We want to make sure that we see something inside our database. assertDatabaseHas, and we're talking about the user table.
We want to make sure that we see something inside our database. Assert database has, and we're talking about the user table. We're providing the class. And now we look for a User with a specific email, which is the one which we just have defined inside the webhook call. And then we also need to provide the name, which I think was testUser. Let me copy this, bring this in here. All right. So this is how we make sure that we now have a new User.
All right. So this is how we make sure that we now have a new User inside our database with the specific fields which we got from our webhook call. But then we also want to make sure now that we have a purchase_course. So we need to test something very similar. assertDatabaseHas, but now for our purchase_course table. PurchaseCourse, we're providing the class here again. And then with an array, we're going to say, we are looking now for some specific data.
And then with an array, we're going to say, we are looking now for some specific data. So what do we have here? First, we have some kind of userId. Let's keep this empty for now. And then we also have a courseId. So this is how we connect the User to a specific Course. And the userId should be one because it should be the first User. And the courseId should also be one because it's also the first Course. But since we, let's check here.
And the courseId should also be 1 because it's also the first course. But since we, let's check here. Yeah, here we are already creating a Course. I think it's even better to just directly call the ID of the Course. So maybe it's not 1, then it's easier and safer to use this. And we could also do this here by just getting a specific User. Let's just look for the one which we have User where, and let's look by email. And the email is test.test@. And we're just looking for the first one.
And the email is test.test@. And we're just looking for the first one. And now we can also use here the userId directly, which I think is a little bit better now because we don't assume what the IDs might be. We're just using the ones directly from the User and from the Course. All right, let's go through it together before we run it. So first, we're going to make sure that both our tables are empty. And again, I told you already, since we're using the RefreshDatabase trait for all of our tests inside the Feature directory,
And again, I told you already, since we're using the RefreshDatabase trait for all of our tests inside the Feature directory, I somehow already know that our tables will be empty. But still for everyone coming just to this test, they probably don't see immediately that we use the RefreshDatabase trait. And for that case, I'd really like to make it very clear what we're doing. We make sure both tables are empty. Then we're creating a Course and we're creating a WebhookCall. Then we are calling our job by providing also the WebhookCall model. And then we're making sure that we have a new User.
Then we are calling our job by providing also the WebhookCall model. And then we're making sure that we have a new User with the details from the WebhookCall. And then we also want to make sure that we have a new purchased course. All right, let's run it and see what we get back. And the error says the table is empty. And here we're talking about the user table. All right, so we don't have a User inside our database. And it's true because inside our handle method, we are doing nothing. So let's change this.
Implement User Creation9:27
And it's true because inside our handle method, we are doing nothing. So let's change this. We're going to create now here a new User, User::create. And we're going to provide an email. And the email we now get through the webhook call, which we have access to inside this job. And then there is a payload. And from the payload, we want to receive the email like this. And this also works now very similar for a name, name, name. And then we also need to provide a new password for our User.
And this also works now very similar for a name, name, name. And then we also need to provide a new password for our User. And I'm just using bcrypt here with a random, take a UUID here for a random string. And this should be enough to create a User with a password. And first, we need to provide here a password because we cannot create a User without a password. But we also don't want to use anything like the email or the name or some kind of combination of those fields for the password. But we don't care what the password is.
or some kind of combination of those fields for the password. But we don't care what the password is because then we're going to tell our User inside the email also to go to the forget password page inside our application and set a new password because you always want your users to set a new password. All right, so I think this should now work to create a User. Let's check. And yeah, it seems because now we have a different error. The table is still empty, but now we're talking about the purchase courses.
Attach Course Purchase10:55
And yeah, it seems because now we have a different error. The table is still empty, but now we're talking about the purchase courses. Okay, so let's handle this one now. So first, we want to make sure that we get a Course which we have inside our database. So let's try to find this course, course where pedal product ID is the one which we get through this, this, WebProcall, payload. And then what is called again? I think it's P_product_ID.
And then what is called again? I think it's $productId. And then let's get the first one. All right, so this is how we get the course. And then since we now have a User, we can use our purchasedCourses relationship here in order to attach now a new course. And it's the attach method and the course. We can now use the User to attach the course which we just found by using the $productId.
We can now use the User to attach the Course which we just found by using the pedalProductId. Let's run the test again. And it's already passing, which is great. So we now have made sure that we can store a PedalPurchase.
