Authentication using API | Bondar Academy
Course: Playwright UI Testing with TypeScript
Module: Interacting with APIs
Instructor: Artem Bondar
Lesson Summary
Lesson Overview: In this lesson, we optimize the authentication process of our application by using an API call instead of a user interface. This change enhances performance by eliminating the need for manual username and password entry. Key Concepts: Authentication Optimization: Replacing UI-based authentication with API requests. User State Management: The authenticated state is saved in a user.json file, which includes: Cookies: Currently empty, as no cookies are used for authentication. Origins: Contains the URL and local storage with the JWT token. Access Token Retrieval: The access token is obtained via an API call and stored in the user.json file. Implementation Steps: Comment out the UI authentication code. Import necessary modules: import user from './user.json'; import { writeFileSync } from 'fs'; Update the user object with the new access token. Write changes back to user.json using: writeFileSync('user.json', JSON.stringify(user)); Store the access token in a process environment variable for reuse: process.env.ACCESS_TOKEN = accessToken; Configure global HTTP headers in playwright-config.ts to use the access token. Conclusion: This lesson demonstrates how to streamline the authentication process by leveraging API calls, improving code readability, and enhancing performance. All tests passed successfully after these modifications.
Video Transcript
In this lesson, I will show you how you can make authentication of your application using just API. This optimization helps to make your execution a little bit faster, because you are technically skipping the entering of your username and password on the screen by replacing it with just API request. And in this lesson, we're going to do this. Let's get into it. In the previous lesson, we created a dedicated auth.setup.ts file that is responsible for authentication. And we are doing this through the user interface, entering username, password, and clicking on the button. And then at the end, we have this step that saves authenticated state of the application, all the information related to authenticated state, into the JSON file, which is user.json. So let's look into that file, what actually was generated. So this is this file, and let's take a look. So it has two objects, cookies and origins. Cookies is empty, so our authentication does not use any cookies. And inside of origin is pretty simple object as well. It's just the name of our URL, then local storage object. And inside of this local storage object, just the value of the token and the name of the token, which is JWT token. And we already know that we can get this token using API call, right? So previously inside of the test, we were getting this token right here. And this is the value of access token that later used in the header to make API request. So technically what we can do, we can replace these steps with just API call and update the value of the token inside of this file from the API response. And this is what we're going to do. So that way we will simplify our code a little bit as well and make it a little bit faster since we will make authentication using API without using user interface at all. So let's do this. Since we won't need UI authentication anymore, I temporarily comment out this code. So we will not use this. Then I go to the tests and just copying the piece of the code where we were getting the API from authentication URL and copying this code right here inside of the test. Okay, it's highlighting that we need to import the request right here to perform the request. What's the next step? So we were getting this access token. And now we need somehow to save this access token inside of this user.json file. How to do that? We need to make two imports inside of the file. First import is the actual user.json file itself. Import user from. And this file is located inside of user.json. And the second import that we need to make is the fs library, which is file sync from fs. This is a built-in library in JavaScript to work with the files, write the files, update the files, and so on. So what we need to do next? The next step, we need to update the user object with the new value. So we call user. Then we use origins. Origins is array. So we select the first value from the array. Local storage. This is array as well. So we put zero. So we want to select the first value. Value equals to access token. All right. So now this user object that we imported from here has the new value token received from the API. But then we need to update this user object, write those changes inside of the file. And for that purpose, we will use fs library. I call fs. Write file sync. And two arguments. First argument, we provide the path to the file, which is auth file. And the second argument will be a user object itself. And we need to use JSON stringify and provide the user object. All right. So that's pretty much it. Let's run this test and see if it is working. So I want to run all the tests. And I click right here. All right. We see that auth indicated state for our application working just fine. All right. Perfect. All tests are passed. So this approach is working. And now we can safely delete this code. All right. So let's look into one more thing. If you look in our previous test, we see that we kind of duplicating this step. So we make a call of access token in delete article. And also we make the call to get the token in create the article. We need this because we need this authorization header right here. Without authorization header, we would not be able to call delete request or here post request. But we already saving this access token right here in setup step. So question. How can we reuse this access token inside of the test without a need of creating this token again and again every time we need to make API call in the test? It's very simple. So we can assign access token value to process environment variable. This is a built-in feature in Node.js. So you just call process.env and then provide the name of environment variable, how we want to save this value. And I call it access token. And it's considered a best practice to put all capital cases for the values related to environment variables. And I assign value over access token. Okay. Now, how can we reuse the value of access token that we assign in the setup step? Let's go to the playwright-config.ts. Here in the use block, not the use block that related to the project, the global one, this one. Here we add a new key called extra HTTP headers. This is the object. Inside of the object, we take this authorization header and paste it right here. The authorization should be a string like this. And value access token is not available, of course. So we need to replace it with the process environment variables. I call process.env.accessToken. Exactly the same variable name that I have created right here in the setup section. And now we can safely go back to our code and delete everything related to the token creation and authorization header itself. So I can delete this code. I can delete authorization header. I don't need it anymore. It will be returned from the playwright-config.ts. What else I can delete? I can delete this step. I don't need to call a token here. And I don't need a header right here as well. So it can be simplified to just one line of code. Well, I guess that's it. We don't have any other places where we call our token. And let's run this test one more time. Yeah, you can see everything works perfectly and all tests are passed. All right. So let's quickly summarize what we did in this lesson. In this lesson, we replaced the authentication process by just calling the API and saving our token inside of the user.json. Because this is the way how our application is authenticated in this particular case. And also we know that our access token is needed to be authenticated and is needed to make an API calls. And in order to reuse this value again and again inside of the test and avoid calling that authorization URL multiple times for every test, we save the value of access token in the process environment variable. Then we configure this process environment variable as authorization header globally for the framework. And then we can simply remove all those instances of calling the authorization URL or headers inside of the API call, which is simplify the code, make it nicer and easier to read. All right. Thank you guys and see you in the next lesson.