Schema Reader | Bondar Academy
Course: Playwright API Testing with TypeScript
Module: Schema Validation
Instructor: Artem Bondar
Lesson Summary
In this lesson, we will create a custom schema validator for Playwright, as it does not support schema validation by default. Our initial step will involve developing a function to read the schema from our project. Resources and References During research, the approach by Butch Mayhew was particularly insightful. His website, playwrightsolutions.com , contains numerous articles on API automation, including a detailed example on validating JSON schema. Project Structure To manage our schemas effectively, we will: Create a new folder named response schemas in the root of the project. Organize schemas by creating subfolders for each endpoint, such as tags and articles . Under each endpoint folder, separate schemas based on the HTTP methods (GET, POST, PUT). Creating the Schema Validator We will create a new file named schema validator.ts in the util folder. The following steps outline the implementation: Import necessary modules: fs from fs/promises and path . Define an asynchronous function loadSchema to read the schema from a file. Use fs.readFile to read the file content and convert it to a JSON object. Implement error handling using a try-catch block to manage potential file reading errors. Validating the Schema We will create another function, validateSchema , which will combine the directory name and file name to construct the full path for the schema file. This function will utilize loadSchema to retrieve and print the schema. After implementing the above steps, we will test the functionality to ensure the schema is read correctly and printed to the console. In conclusion, this lesson sets the foundation for schema validation in Playwright, and we will continue to build upon this in future lessons.
Video Transcript
All right, guys, in this lesson, we will start working on custom schema validator. Unfortunately, Playwright does not support schema validation by default, so we will need to create a custom function that will do it for us. As a first step, we will create in this lesson a function that just reads this schema in our project, so then we'll later can validate it. Let's jump into it. Before we begin, I wanted to show you this website, playwrightsolutions.com. So when I was researching the subject on the schema validation, I found the approach of Butch Mayhew as quite interesting. This is what I will show you in this lesson. So he has a lot of articles related to API automation. There is 16 parts over here, so quite a lot of useful information. And specifically, this validating JSON schema is the example that I was using to prepare for this module. And of course, I updated, modified, and improved his approach a lot, but still, his approach I like the most. So I just wanted to give him a credit for very nice content, all right? So and we continue. So let's open our project. Here it is. And first of all, we need to decide how we're going to manage our schemas. And for that, let me create a new folder in the root of the project, and I will call it response schemas, something like this. And then inside of this folder, I would like to create a folders pair resource, pair path name for better convenience and better management down the road. So for example, we have the tags endpoint, articles endpoint. We later may have other endpoints. So far, our project has just two endpoints. And endpoints may have several methods. For example, tags endpoint in our example, only work with the get request. But for example, article endpoints, it has get request, it has post request, it also has a put request. So three different types of requests pair endpoint. And for better management of the schemas, it would be nicer to separate them into the folders pair endpoint. And under each folder, we will have, for example, several schemas. For articles, we will have three schemas, one for get, one for post, and one for the put request. So that way, you will keep your project nicely organized, and all your schemas will be nicely structured down the road. So this is what we're gonna do. Response schema, I create new folders according to the endpoint name. So it's gonna be tags folder, and the second will be new folder articles, like this. So under tags, I will put all schemas related to the tags endpoint. Under articles, all schemas related to articles endpoint. And let's start, as always, with the most simple one. Tags endpoint, it will be our first example to read the tag schema. So let's get the tag schema first. So that's our endpoint, send the request, this is the response object. Let's generate the schema, I put the object over here. Schema is generated, copying this content. And I will create a new schema under this folder, so a new file. And the name I will provide according to the method that was used to get this schema under tags endpoint. So it will be get underscore tags underscore schema dot JSON. So this naming convention will help us to keep all files nicely organized with meaningful names. And I'll just copy the file over here, that's it. So our schema inside of the project. Now, we need to read this schema, so later we'll be able to validate it. How are we gonna do this? So let's begin with creating a custom schema validator under the util folder. So I start new file, and I call it schema validator.ts. The empty file, start fresh, and start new, as always. All right, first of all, we need to import a couple of helpers that we're gonna need working with the file. So first of one, import fs from fs promises. And second one, import path from path. So what is that? Fs is also acronym for file sync, is the library in Node.js to interact with the files and folders and operate with the files in the file systems of our project. And path is also another module in the Node.js. It's just convenient to create the path out of the separate components to get the resulting path to the file if we want to read a certain file. Just a convenient thing to have. All right, we have two of those helpers, and then let's use them. So I will create a first function, a sync function. And the function will be load schema. This function will read the schema from file. So the argument will be a schema path, which is a type of string. So we will provide the path into this function, and this function will return us object with the schema. That's all we want it to do. Then I create a new constant, schema content, for example. Schema content equals to await. I call fs to read the file, and fs has this nice method, read file, that can read any file in our project. And what I need to provide is just the path to this file, and also to convert this file to a string, because read file returns a buffer. But we need to return it as a string right away. So we converted this data stream to a string format right away. We can use coding, which is UTF-8, like this. So this value will be a JSON object in the format of the string. And then we need to convert this JSON object from the string format into actual object format. And you can do a json.parse command, and pass this object as the argument, like this, and just return this object. So that's it. Now our function will return a JSON object, reading it from the file. And to make this function more error resilient, let's wrap it up in the try-catch block, like this. So I'm gonna put this over here in try block. And if there is a new error, throw new error. Let's bring the error message, something like failed to read the schema file. And the error message, message what happened and what went wrong. Because sometimes maybe path provided incorrectly, or maybe file is not available, or something like that. So if the read file will not be able to read the file, we want to know it, and we want to throw the meaningful error with the details what actually went wrong. So we need this try-catch block. So that's it, we have a function. Now let's try to use this function. And I will create a new function, export async function. That will be actually our schema validator in the future. Validate schema, like this. So which parameters do we need? For parameters, I would like to use the directory name and the file name. So two parameters. Out of those two parameters, we will combine the path to our resulting file. So this is how we're gonna read the files in different folders and with different names. So first argument will be directory name, which is a string. And the second argument will be a file name, which is also be a string. So to read this path, we're gonna need the response schemas plus directory name, which either articles or tags, and the file name. So let's create one more constant, which I called schema base path, something like this. And the base path is response schemas, correct? Response schemas, response schemas, okay, it's correct. And now let's build the path to the file. Schema path equals to path.join. And now we're gonna use this helper that we imported before, path.join. And let's open all the arguments that we have. First of all, a schema base path, then directory name. And then we need a file name. File, I need with a backticks like this. So it's gonna be a file name, and then underscore, and it is schema.json. Okay, so the file name will be the actual file I get underscore text, and it will be appended to underscore schema.json. So this entire thing should give us the resulted full path relatively to the project to read this file, okay? So now let's finally use this load schema method. So schema path, and then const schema equals to load schema. And we provide schema path. That's it, let's print it out to the console. Console.log and schema. So I think that's it. So now this function should read the schema from file, and let's just test if it is working as expected. So going back to the smoke test.spec.ts, I'll take this get text playground for experiments. And I will need to code a weight validate schema like this. And I need to provide two arguments, the directory name, a file name. So directory name is tags. And the file name is get tags like this. And if we didn't make any mistake, we in theory should see the schema printed into the console. Let's run the test, and it almost worked. So it's printed something, but we don't see the entire schema. So we did a mistake somewhere. So let's check it out, and aha, I forgot to use a weight over here. Because load schema is a sync function, so I had to use a weight. Let's try it one more time, and okay, perfect. Right now it's working as expected. You can see the entire schema file was printed in the console. So load schema method is working, and now we can use this method to actually validate this schema and add the validator that is gonna do this for us. All right, so that's it guys, and see you in the next lesson.