Awesome video! Just a quick note: At 2:07 you mentioned "the backend of the page," which might be slightly misleading because that's not the correct term.
Hi Ragav, when I was tried await page.locator('id=user-name').fill('Edison'), like the video it should enter the value into the element, However when i checked the inspector logs page.locator('id=user-name') .fill() it throws this message and Edison is not formulated into that field, can you please give me suggestion for what needs to be done. Thank you
Anurag I'd be glad to help you with the Playwright error you're encountering when trying to fill in the username field. Here are the main areas to consider and potential solutions: 1. Verify Element Selection: - Double-check Selector: Ensure the `'id=user-name'` selector accurately targets the desired username input element. Use the browser's developer tools to inspect the element and confirm its ID. - Use Other Locators: If the ID is unreliable, try alternative selectors like `xpath` or `css` that more definitively identify the field. Playwright offers flexibility in selecting elements: 2. Handle Dynamic Elements: - Wait for Visibility: If the element isn't immediately visible or ready for interaction, add `await page.waitForSelector('id=user-name')` before `fill()` to ensure it exists in the DOM and is interactable. - Check Element State: Verify that the element isn't disabled or otherwise prevented from accepting input using `await element.isDisabled()`. 3. Clear Existing Value: - Clear Before Filling: Use `await element.fill('')` to clear any pre-filled value before entering "Edison". This can be necessary if the field initially has content. 4. Handle Element Visibility and Positioning: - Scroll into View: If the element is not in the viewport, use `await page.locator('id=user-name').scrollIntoView()` to make it visible before interacting. - Handle Overlapping Elements: If other elements might be obscuring the field, verify their positioning and use techniques like `click()` or `hover()` to interact with the username field effectively. 5. Inspect Browser Console and Network Logs: - Check for JavaScript Errors: Look for any JavaScript errors in the browser console that might be preventing the form from functioning correctly. - Verify Network Requests: Ensure successful network requests for form submission or data updates if applicable. 6. Handle Frame or Shadow DOM: - Switch to Frames: If the element is within an , use `await page.frame('frame-name').locator('id=user-name').fill('Edison')` to switch to the appropriate frame. - Handle Shadow DOM: If the element is within a Shadow DOM, use `await page.$$eval('.shadow-selector', elements => elements[0].querySelector('#user-name')).fill('Edison')` to interact with it.
One debate when talking to others is what selector type is best to use. Some say ID some say Xpath. When all are available to an object on the browser which selector type is best to use and why? Is there an order of best to least desirable selector type to use? Thanks so much!!
Tom You're right, there is a preferred order for choosing selectors in web development, and it aims for a balance between efficiency and maintainability. Here's the breakdown: Most Desirable: * ID Selector (`#id`): IDs are unique within a document, making them very specific and efficient for selecting a single element. Use them when you need to target a specific element with a guaranteed unique ID. Less Desirable, But Good: * Class Selector (`.class-name`): Classes can be applied to multiple elements, offering more flexibility than IDs. They are reusable and promote better code organization. Use them when you need to style a group of elements with the same characteristics. Even Less Desirable, Use with Caution: * Type Selector (`element-name`): These target all elements of a specific type (e.g., `p` for paragraphs). They can be slow and inflexible, especially for complex pages with many elements of the same type. Use them sparingly, and only when you absolutely need to target all elements of a specific type. Least Desirable (Avoid if Possible): * XPath: While XPath is powerful and can target almost any element, it's complex, slow for browsers to parse, and can become brittle if the HTML structure changes. It's generally recommended to avoid XPath unless there's absolutely no other way to achieve what you need. Here's why this order is preferred: * Specificity: More specific selectors (ID > Class > Type) take precedence over less specific ones in case of conflicting styles. This makes your code more predictable and easier to maintain. * Performance: Browsers can process simpler selectors (ID, Class) faster than complex ones (XPath). * Maintainability: Using IDs and Classes makes your code more readable and easier to update if the HTML structure changes. Relying on fragile selectors like XPath makes maintenance difficult. In summary: * Aim for ID selectors when targeting unique elements. * Use class selectors for reusable styles on multiple elements. * Use type selectors cautiously and only when necessary. * Avoid XPath unless absolutely essential.
Hi Raghav. Thanks so much for your tutorials. I have been making presentations during sprint reviews and I would appreciate it very much if you don’t mind sharing with me the tool you use to draw the rectangular shapes around the texts on the screen. Thank you.
Hi @RaghavPal, your lessons and explanations are really great. But on the official site of Playwright about Locators, it is recommended to use built-in locators rather than css and xpath. So is it possible to add a lesson on how we can use built-in-locators manually in addition to this lesson? Thanks in advance 🙏
Alp Playwright provides a robust set of built-in locators that enhance test reliability and maintainability. Let's delve into how you can manually use these locators to locate elements on a page. 1. By Role (Recommended): - The `page.getByRole()` locator is based on how users and assistive technology perceive the page. It's particularly useful for locating elements like buttons, checkboxes, headings, links, and more. - To use it, pass the accessible name (usually the text associated with the element) along with the role. For instance: ```javascript await page.getByRole('button', { name: 'Sign in' }).click(); ``` - You can also use regular expressions for matching names: ```javascript await page.getByRole('button', { name: /submit/i }).click(); ``` 2. By Text Content: - Use `page.getByText()` to locate elements based on their visible text content. For example: ```javascript await expect(page.getByText('Welcome, John!')).toBeVisible(); ``` 3. By Label: - To locate form controls by their associated label's text, use `page.getByLabel()`. Example: ```javascript await page.getByLabel('User Name').fill('John'); ``` 4. By Placeholder: - Use `page.getByPlaceholder()` to locate an input element by its placeholder text. 5. By Alt Text: - Locate elements (usually images) by their alternative text using `page.getByAltText()`. 6. By Title Attribute: - Use `page.getByTitle()` to locate an element by its `title` attribute. 7. By Test ID: - If your elements have custom `data-testid` attributes, you can use `page.getByTestId()` to locate them. Remember, prioritize user-facing attributes and explicit contracts like `page.getByRole()` for resilient tests. You can chain these locators to iteratively narrow down your search. For instance: ```javascript const locator = page.getByRole('button', { name: 'Sign in' }); await locator.hover(); await locator.click(); ```
@@RaghavPalThank you very much for your valuable explanations🎯. But still, it would be great to see a video (lesson) that covers these topics with your unique explanation 🙏
As of the latest version of Playwright Inspector (1.17.0), the Explore feature has been moved to a separate standalone tool called Playwright Inspector DevTools extension. You can install the Playwright Inspector DevTools extension from the Chrome Web Store and use it to explore and interact with elements on your webpage. Make sure to update to the latest version to access this feature.
To see what happens during opening a PDF file uploaded on a web page in the backend on Playwright, you can use the following steps: 1. Open the Playwright browser that you want to use for testing. 2. Navigate to the web page where you can upload PDF files. 3. Upload a PDF file to the web page. 4. Open the Developer Tools in the Playwright browser. 5. Go to the Network tab in the Developer Tools. 6. Click the Clear button to clear the network log. 7. Click the Record button to start recording the network traffic. 8. Click the link to open the uploaded PDF file. 9. Click the Stop button to stop recording the network traffic. 10. Inspect the network log to see what happens during opening the uploaded PDF file. You can also use the Playwright `Network` class to inspect the network traffic. The `Network` class provides a variety of methods for getting information about the network requests and responses that are sent between the Playwright browser and the backend server. Here is an example of how to use the `Network` class to inspect the network traffic during opening an uploaded PDF file: ```python import asyncio from playwright.async_api import async_playwright async def main(): async with async_playwright() as p: browser = await p.chromium.launch() page = await browser.new_page() await page.goto('example.com/upload-pdf') # Upload a PDF file. await page.locator('[type="file"]').set_input_files('my-pdf.pdf') await page.locator('[type="submit"]').click() # Wait for the PDF file to be uploaded. await page.wait_for_navigation() # Open the uploaded PDF file. await page.locator('[href="my-pdf.pdf"]').click() # Get the network traffic. network = page.network traffic = await network.get_traffic() # Inspect the network traffic. for request in traffic: print(request.url) if __name__ == '__main__': asyncio.run(main()) ``` This code will print the URLs of all of the HTTP requests that are sent between the Playwright browser and the backend server during opening the uploaded PDF file. I hope this helps
Hi Raghav, could you please cover how to handle dynamic web table in playwright with JavaScript? It would be great help. It's looking like no one covered this topic in JavaScript.
Hi Raghav Firstly I want to say how useful these videos are as I am new to coding. Secondly, at 12:22 the object was identified and worked for me too but when i clicked on step over it didn't click in the username field but instead my inspector stopped. Can you please let me know what could be the reason. Thanks
Hi Raghav, excellent tutorial - I am sharing your content wherever my contract is!! I notice that now the Playwright selectors web page is no longer there under the reference given - wonder why it has gone in last 3 months?
Sirisha Yes, you need to give a # before the locator if you are using a CSS ID selector. A CSS ID selector is a unique identifier for an element on a page. To select an element using a CSS ID selector, you use the following syntax: ``` #id-of-element ``` For example, to select the element with the ID `login-button`, you would use the following selector: ``` #login-button ``` You do not need to give a # before the locator if you are using a different type of CSS selector, such as a class selector or a tag selector. Here are some examples of other CSS selectors: ``` .class-of-element ``` ``` tag-name ``` ``` tag-name.class-of-element ``` ``` tag-name:nth-child(n) ``` ``` tag-name:hover ``` ``` tag-name:active ``` You can learn more about CSS selectors in the following documentation: * CSS Selectors: developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors I hope this helps
To select test time out from config.js if timeout does not exist in config.js file using Playwright, you can use the following code: ```javascript const config = require('./config.js'); // Get the test timeout from config.js, or use a default value of 10000 milliseconds (10 seconds) if timeout does not exist in config.js. const testTimeout = config.timeout || 10000; // Set the test timeout for Playwright. test.setTimeout(testTimeout); ``` This code will first check if the `timeout` property exists in the `config.js` file. If it does, the code will use the value of the `timeout` property as the test timeout. If the `timeout` property does not exist in the `config.js` file, the code will use a default value of 10000 milliseconds (10 seconds) as the test timeout. Here is an example of how to use the above code in a Playwright test: ```javascript const config = require('./config.js'); // Get the test timeout from config.js, or use a default value of 10000 milliseconds (10 seconds) if timeout does not exist in config.js. const testTimeout = config.timeout || 10000; // Set the test timeout for Playwright. test.setTimeout(testTimeout); test('should open the Google homepage', async () => { const browser = await test.newBrowser(); const page = await browser.newPage(); await page.goto('www.google.com/'); // Assert that the Google homepage is open. expect(await page.title()).toBe('Google'); await browser.close(); }); ``` If the `timeout` property does not exist in the `config.js` file, the above test will have a timeout of 10 seconds.
Hi, In Appium, you can use the "findElement" method and the "xpath" locator to select a nested text element like the one you described Here is an example /* WebElement element = driver.findElement(By.xpath("//div[@class='errors']/b")); String text = element.getText(); */ This code will locate the element that is nested inside the element, and then extract the text content of the element using the getText() method
Hi Nomandla For Playwright API Testing, I need to create, but there are other API Testing videos, Can check the section here - automationstepbystep.com/
Dev Let's break down the problem step by step Problem Statement: You have 5 images on a webpage, each with a header and a link. You want to automate testing using Playwright to cover all 5 images in a single iteration. Step 1: Inspect the HTML structure Open the webpage in a browser and inspect the HTML structure of the images using the developer tools. Identify the common CSS selectors or XPath expressions that can be used to locate all 5 images. For example, let's assume the HTML structure is: ```html Header 1 Link 1 Header 2 Link 2 ``` In this case, we can use the CSS selector `.image-container` to locate all 5 images. Step 2: Use Playwright to locate all images In your Playwright script, use the `page.$$` method to locate all elements that match the CSS selector `.image-container`. This will return an array of elements. ```javascript const images = await page.$$('.image-container'); ``` Step 3: Iterate over the images and extract header and link text Use a `for` loop to iterate over the `images` array and extract the header and link text for each image. You can use the `element.querySelector` method to locate the header and link elements within each image container. ```javascript for (const image of images) { const header = await image.querySelector('h2'); const link = await image.querySelector('a'); const headerText = await header.textContent(); const linkText = await link.textContent(); const linkHref = await link.getAttribute('href'); // Do something with the extracted data, e.g., log it to the console console.log(`Image Header: ${headerText}, Link: ${linkText} (${linkHref})`); } ``` Step 4: Verify the extracted data (optional) If you want to verify that the extracted data is correct, you can add additional assertions or checks within the loop. That's it! With these steps, you should be able to cover all 5 images in a single iteration using Playwright.
Thank you for your lecture. I've test many times, under line await page.click('id="user-name"') but debug window's 'step over' and other buttons are disabled at this line. so I change like this await page.click('[id="user-name"]') it is worked. Could you check this please?
Hi sir could you please help me to solve the issue in playwright with js i have requirements like if I have to create some data on web ui and then I have to click save as button on web ui.if i click on save as the desktop save as window will open there i can edit file name and click on save button to save the ui data in local.but i don't have input file option to do with playwright . Could you help me to solve this issue .
Sanjeev It seems you want to automate the process of saving data from a web UI as a local file using Playwright. Unfortunately, Playwright doesn't directly support the "Save As" dialog for web pages. However, I can suggest a couple of workarounds: 1. Print to PDF: - You can emulate the "Save as PDF" functionality by printing the web page to a PDF directly from Playwright. - Here's an example in Python: ```python from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto("your_url_here") # Emulate print media type await page.emulate_media("print") # Generate PDF await page.pdf(path="output.pdf", format="A4") browser.close() ``` - Adjust the URL and file path as needed. 2. Keyboard Shortcuts: - If the "Save as" option is accessible via keyboard shortcuts (e.g., Ctrl + S), you can simulate those key presses using Playwright. - First, focus on the desired element (e.g., the web page content). - Then, send the keys for the shortcut (e.g., Shift + F10, arrow keys, and Enter) to trigger the "Save as" action Remember to adapt these solutions to your specific use case. If neither of these options works for your scenario, consider exploring other automation tools or libraries that might better suit your needs. Good luck -
Hi Raghav, thanks for the series. Can you please help me in the following. When I am trying to get the dropdown options using the following code, I am getting null and undefined values on lines 1 & 2 respectively. Plese help here. const state=await page.$('#state'); const stateoptions=await state.$$('option');
Sravanthi Let's address the issue you're facing. 1. Getting the Selected Option Value: - To get the selected option value from a dropdown, you can use the following code: ```javascript const selectedValue = await page.$eval('#state', sel => sel.value); console.log('Selected value:', selectedValue); ``` - Replace `#state` with the actual selector for your dropdown element. This code will return the value of the currently selected option. 2. Getting the Selected Option Text: - To get the text of the selected option, you can use: ```javascript const selectedText = await page.$eval('#state', sel => sel.options[sel.selectedIndex].textContent); console.log('Selected text:', selectedText); ``` - Again, replace `#state` with your actual selector. This code retrieves the text content of the currently selected option. 3. Complete Example: - Here's how you can combine both approaches: ```javascript const state = await page.$('#state'); const selectedValue = await page.$eval('#state', sel => sel.value); const selectedText = await page.$eval('#state', sel => sel.options[sel.selectedIndex].textContent); console.log('Selected value:', selectedValue); console.log('Selected text:', selectedText); ``` - Make sure to adjust the selector (`#state`) to match your specific dropdown element. Remember to replace `#state` with the actual selector for your dropdown
@@RaghavPal Thank you so much Raghav. I learnt couple of new things from your comment now. Trying with the following code, I am able to now get the whole list of dropdown options(static one). But why am I seeing the error message "Object possibly null" here (at the code, on mousehover) but finally it works fine. Confused in this point. Can you pl explain in brief. await(await (await page.$("#state")).$$("option")).forEach(async o=>console.log(await o.textContent() as unknown as string));
Let's break down the code snippet you provided and address the points of confusion: 1. Getting Dropdown Options: - The code you shared aims to retrieve the text content of all `` elements within a dropdown (select) element with the ID `"state"`. - The `await page.$("#state")` part selects the dropdown element. - The `await (await page.$("#state")).$$("option")` part selects all `` elements within the dropdown. - Finally, the `.forEach(async o => console.log(await o.textContent() as unknown as string))` loop iterates through each option and logs its text content. 2. "Object Possibly Null" Error: - The error message "Object possibly null" occurs because TypeScript (or JavaScript) is warning you that the result of `await page.$("#state")` could be `null`. - This warning is due to the possibility that the element with the ID `"state"` might not exist on the page. - When you use `await` with `page.$("#state")`, it returns a `null` value if the element is not found. - To avoid this warning, you can add a null check before accessing the options: ```javascript const dropdown = await page.$("#state"); if (dropdown) { const options = await dropdown.$$("option"); options.forEach(async o => console.log(await o.textContent() as unknown as string)); } ``` 3. Why It Works Fine Anyway: - Despite the warning, your code works because Playwright handles the `null` case gracefully. - If the element is not found, the `await page.$("#state")` expression resolves to `null`, and subsequent operations (such as `.forEach`) are simply skipped. - So, even though TypeScript warns you about the possibility of `null`, Playwright ensures that the code doesn't break. 4. Best Practice: - To improve readability and avoid the warning, consider using a null check as shown above. - Additionally, you can handle any specific logic (e.g., error handling) if the element is not found. Remember that TypeScript's static analysis helps catch potential issues early, but in this case, Playwright's runtime behavior ensures that your code works as expected ---
@@RaghavPal Thank you so so much Raghav for such a detailed explanation. Love to watch your videos always which targets on the pin pointed explanation within short duration. Thanks once again.
Moataz To see what happens during uploading to PDF files to your web app in the backend, you can use a variety of tools and techniques. One way to see what happens during uploading is to use a network capture tool, such as Wireshark or Fiddler. Another way to see what happens during uploading is to use a debugger, such as Visual Studio Code or IntelliJ IDEA. Finally, you can also use the logging features of your backend server to see what happens during uploading. For example, you can log the names of the uploaded files, the sizes of the uploaded files, and the timestamps of the uploaded files. This information can be useful for troubleshooting problems with uploading PDF files. Here are some specific steps that you can take to see what happens during uploading to PDF files to your web app in the backend: 1. Open a network capture tool, such as Wireshark or Fiddler. 2. Start the network capture tool. 3. Upload a PDF file to your web app. 4. Stop the network capture tool. 5. Analyze the network traffic to identify the specific HTTP requests that are used to upload PDF files to the backend. 6. Open a debugger and attach it to the backend server. 7. Set a breakpoint at the beginning of the code that is used to process uploaded PDF files. 8. Upload a PDF file to your web app. 9. Step through the code in the debugger to see what happens during uploading. 10. Enable logging on the backend server. 11. Upload a PDF file to your web app. 12. Check the logs to see what information is logged about the uploaded file. I hope this helps
in my code i insert var hrefs = await page.evaluate(() => { return Array.from(document.links).map(item => item.href); }); but i have different result with or without --header how can i solve this?
Hi Almanacco, If you are seeing different results when using the --header option in Playwright, it is possible that the server you are interacting with is returning different content based on the headers that are sent with the request. When you use the --header option, you are specifying additional headers to be sent with the request. If the server is checking for the presence of certain headers, or if it is using the headers to determine the response that is sent, then the results could be different. One way to solve this would be to investigate what headers the server is expecting, and make sure that you are sending the correct headers with your request. You can inspect the requests being sent by using the browser's built-in developer tools, or by using a tool like Wireshark to inspect the network traffic. Another approach would be to try to make the request without the --header option and inspect the response to see if there are any clues about what headers are needed. You could then try adding those headers to your request using Playwright's setExtraHTTPHeaders method. For example, you could try something like this: //javascript await page.setExtraHTTPHeaders({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36' }); var hrefs = await page.evaluate(() => { return Array.from(document.links).map(item => item.href); }); This sets the "User-Agent" header to the same value that is sent by Chrome, which may help to make the request look more like it is coming from a real browser
Hi Rohan Yes, In Playwright, you have the option to use the Test Recorder to automatically generate code by interacting with the web application. However, knowledge of manual process will also be handy in some scenarios 1. Complex Scenarios: The Test Recorder may not capture all the interactions or scenarios you need to test. In complex test cases, you may have to manually find and interact with specific elements that are not covered by the Test Recorder. 2. Customization and Flexibility: Manual identification allows you to fine-tune your element selection based on specific attributes or conditions that are not captured by the Test Recorder. You can use custom selectors or additional properties to locate elements precisely as per your requirements. 3. Dynamic Elements: In dynamic web applications, elements may have dynamic IDs, classes, or attributes that are not consistently predictable. Manually finding elements allows you to adapt to such changes and handle dynamic elements more effectively. 4. Code Reusability: Manually locating elements allows you to create reusable functions or methods for interacting with specific elements across multiple tests or test cases. This promotes code modularity and makes maintenance easier. 5. Non-UI Testing: Not all tests involve direct interaction with the UI. Some tests may require accessing backend APIs, database validations, or other non-UI related tasks. In such cases, manual element identification is necessary to test these non-UI components. It's important to note that the Test Recorder can be a valuable starting point for creating your tests, especially for simple scenarios or when you're new to Playwright. However, as your test cases become more complex and require advanced interactions, you may find the need to manually locate elements to achieve the desired level of control and flexibility
Sirisha To select a value from drop-downs, radio buttons, and checkboxes using Playwright, you can use the following methods: Drop-downs: Use the selectOption() method to select an option from a drop-down. Here is an example: await page.selectOption('#myDropdown', { value: 'optionValue' }); Radio buttons: Use the click() method to select a radio button. Here is an example: await page.click('#myRadioButton'); Checkboxes: Use the click() method to toggle the state of a checkbox. Here is an example: await page.click('#myCheckbox'); Note that you need to provide the correct selector for each element to interact with it using Playwright. Also, make sure that the element is visible and enabled before interacting with it. You can use the waitForSelector() method to ensure that the element is ready to be interacted with.
How to capture this error message from this "alert error" class ? Playwright is unable to locate this. I've tried xpath, css and other locator options... Your account is invalid or not active. Please contact us for help.
Hi Raja, In Playwright, you can capture the error message from an "alert error" class by using the page.waitForSelector method and then getting the text content of the selected element. Eg: const element = await page.waitForSelector('.alert.error'); const errorMessage = await page.evaluate(element => element.textContent, element); console.log(errorMessage);
@@RaghavPal Thank you. this fixed my issues. Do you have any videos regarding integrations between Playwright framework and TestRails ? If no videos, any recommendations ? Thanks.
No, it is not possible to click using the screenshot.png selector in Playwright. The screenshot.png selector is a visual selector that allows you to identify an element by its appearance in a screenshot. It is primarily used for debugging and troubleshooting purposes.
Sirisha To automate a hamburger button or a menu in Playwright, you can use the following steps: 1. Locate the hamburger button or menu element. You can use the `Locator` class to locate the element by its CSS selector, XPath, or other selector. 2. Click on the hamburger button or menu element. You can use the `Locator.click()` method to click on the element. 3. Wait for the menu to open. You can use the `Locator.waitFor()` method to wait for the menu to open. 4. Interact with the menu items. You can use the `Locator` class to locate the menu items and interact with them using the `Locator.click()`, `Locator.hover()`, and other methods. Here is an example of a Playwright script that automates a hamburger button and menu: ```javascript const { test, expect } = require('@playwright/test'); test('Automate hamburger button and menu', async ({ page }) => { // Locate the hamburger button element. const hamburgerButton = page.locator('.hamburger-button'); // Click on the hamburger button. await hamburgerButton.click(); // Wait for the menu to open. await page.waitForSelector('.menu'); // Locate the menu items. const menuItems = page.locator('.menu-item'); // Click on the first menu item. await menuItems.first().click(); // Assert that the first menu item is selected. await expect(menuItems.first()).toBeChecked(); }); ``` You can modify this script to automate the specific hamburger button or menu that you are working with.
@@RaghavPal Thanks Raghav i really appreciate the help for the detailed code but in my application the Hamburger menu - hides and opens the left nav there is no drop down but how it is is click on the left nav it Expands the left nav and collapses the left nav need to automate that using playwright but am getting errors that target closed and not ale to find locators. I feel that i have written up the correct xpath but trying my best in various ways to solve it.
Here are some things to try when automating a left nav that hides and opens using Playwright: 1. Check the HTML and CSS of the left nav to make sure you have the correct locator. 2. Try using a different locator, such as a CSS selector or a text selector. 3. Try using the `frame()` method to switch to the frame that contains the left nav. 4. Try using the `waitForNavigation()` method to wait for the page to navigate after clicking on the left nav. 5. Try using the `evaluate()` method to evaluate JavaScript on the page. Here is an example of how to use the `evaluate()` method to automate a left nav that hides and opens using Playwright: ``` import { test, expect } from '@playwright/test'; test('Automate hidden left nav', async ({ page }) => { // Wait for the left nav to be visible. await page.waitForSelector('.left-nav'); // Evaluate JavaScript on the page to expand the left nav. await page.evaluate(() => { document.querySelector('.left-nav').classList.add('expanded'); }); // Wait for the left nav to be expanded. await page.waitForSelector('.left-nav.expanded'); // Evaluate JavaScript on the page to collapse the left nav. await page.evaluate(() => { document.querySelector('.left-nav').classList.remove('expanded'); }); // Wait for the left nav to be collapsed. await page.waitForSelector('.left-nav:not(.expanded)'); }); ``` You can also try using a third-party library to automate the left nav. For example, the `Playwright Extras` library includes a `LeftNav` class that can help you automate left navs. I hope this helps
How is it possible to click on the "Login" button twice? await page.locator('text=LOGIN').click() await page.locator('input:has-text("LOGIN")').click()
To click the "Login" button twice using Playwright, you can use the `click()` method on the same locator twice. However, your current code uses two different locators. If you want to click the same button twice, you should use the same locator both times. Here's how you can do it: ```javascript // Click the "Login" button twice using the same locator await page.locator('text=LOGIN').click(); await page.locator('text=LOGIN').click(); ``` Alternatively, if you need to ensure a delay between the two clicks, you can add a `waitForTimeout` between the clicks: ```javascript // Click the "Login" button twice with a delay await page.locator('text=LOGIN').click(); await page.waitForTimeout(1000); // Wait for 1 second await page.locator('text=LOGIN').click(); ``` If you specifically need to use different locators for some reason, ensure both locators correctly identify the same "Login" button: ```javascript // Click the "Login" button twice using different locators await page.locator('text=LOGIN').click(); await page.locator('input:has-text("LOGIN")').click(); ``` Make sure the locators you use correctly identify the "Login" button on your page. -
@@RaghavPal Thank you for your answer. Yes, I'm using two different locators of one element - the "Login" button as in the video. The question is: how can you click on the same button twice? After clicking the "Login" button once, the next page should open and the "Login" button shouldn't be available for the second click. In this video there are two lines of code clicking the "Login" button
@@RaghavPal 31:21 lines of code 18,19. But now I see that it works as expected. There was no command to enter a password so you could click on the "Login" button two or more times. It was my mistake
When I run my test with this command "npx playwright test .\tests\myfirst.spec.js --headed", I get the error no test found but test would run successfully when I run with "npx playwright test myfirst.spec.js --headed"
Faith The reason why you are getting the "No tests found" error when you run the command `npx playwright test .\tests\myfirst.spec.js --headed` is because the Playwright test runner is looking for test files in the current directory. When you specify the path to the test file, the Playwright test runner is not able to find the file because it is not in the current directory. However, when you run the command `npx playwright test myfirst.spec.js --headed`, the Playwright test runner is able to find the test file because you are not specifying the path to the test file. To fix this, you need to make sure that the test file is in the current directory. You can do this by moving the test file to the current directory or by using the `cd` command to change to the directory where the test file is located. For example, if the test file is located in the `tests` directory, you can run the following command to change to the `tests` directory: ``` cd tests ``` Once you are in the `tests` directory, you can run the command `npx playwright test myfirst.spec.js --headed` and the Playwright test runner will be able to find the test file. Another reason why you might be getting the "No tests found" error is because the test file does not contain any tests. A test file must contain at least one test function. If the test file does not contain any test functions, the Playwright test runner will not be able to find any tests. To fix this, you need to add a test function to the test file. A test function is a function that starts with the `test` keyword. For example, the following is a valid test function: ``` test("My first test", () => { // Your test code goes here }); ``` Once you have added a test function to the test file, you should be able to run the test file without getting the "No tests found" error. I hope this helps
This playlist is extremely helpful. 👌
Thanks, Raghav, I appreciate your efforts.😇
Most welcome Umesh.. keep learning
You're the best, I was struggling with Playwright and now my test work as expected!
Great to hear this
Great tutorial, thanks Raghav!!
Glad it helped Simon
THANK YOU SO MUCH. I was looking it forever
Most welcome
Awesome Raghav.
Thanks Bharat
Nice video... You are for sure an pal in automation (couldn't resist, sorry ;) )
No worries
Awesome video!
Just a quick note:
At 2:07 you mentioned "the backend of the page," which might be slightly misleading because that's not the correct term.
Thanks for informing Shay, pls let me know the better option here
Hi Ragav,
when I was tried await page.locator('id=user-name').fill('Edison'), like the video it should enter the value into the element, However when i checked the inspector logs page.locator('id=user-name')
.fill() it throws this message and Edison is not formulated into that field, can you please give me suggestion for what needs to be done.
Thank you
Anurag
I'd be glad to help you with the Playwright error you're encountering when trying to fill in the username field. Here are the main areas to consider and potential solutions:
1. Verify Element Selection:
- Double-check Selector: Ensure the `'id=user-name'` selector accurately targets the desired username input element. Use the browser's developer tools to inspect the element and confirm its ID.
- Use Other Locators: If the ID is unreliable, try alternative selectors like `xpath` or `css` that more definitively identify the field. Playwright offers flexibility in selecting elements:
2. Handle Dynamic Elements:
- Wait for Visibility: If the element isn't immediately visible or ready for interaction, add `await page.waitForSelector('id=user-name')` before `fill()` to ensure it exists in the DOM and is interactable.
- Check Element State: Verify that the element isn't disabled or otherwise prevented from accepting input using `await element.isDisabled()`.
3. Clear Existing Value:
- Clear Before Filling: Use `await element.fill('')` to clear any pre-filled value before entering "Edison". This can be necessary if the field initially has content.
4. Handle Element Visibility and Positioning:
- Scroll into View: If the element is not in the viewport, use `await page.locator('id=user-name').scrollIntoView()` to make it visible before interacting.
- Handle Overlapping Elements: If other elements might be obscuring the field, verify their positioning and use techniques like `click()` or `hover()` to interact with the username field effectively.
5. Inspect Browser Console and Network Logs:
- Check for JavaScript Errors: Look for any JavaScript errors in the browser console that might be preventing the form from functioning correctly.
- Verify Network Requests: Ensure successful network requests for form submission or data updates if applicable.
6. Handle Frame or Shadow DOM:
- Switch to Frames: If the element is within an , use `await page.frame('frame-name').locator('id=user-name').fill('Edison')` to switch to the appropriate frame.
- Handle Shadow DOM: If the element is within a Shadow DOM, use `await page.$$eval('.shadow-selector', elements => elements[0].querySelector('#user-name')).fill('Edison')` to interact with it.
One debate when talking to others is what selector type is best to use. Some say ID some say Xpath. When all are available to an object on the browser which selector type is best to use and why? Is there an order of best to least desirable selector type to use? Thanks so much!!
Tom
You're right, there is a preferred order for choosing selectors in web development, and it aims for a balance between efficiency and maintainability. Here's the breakdown:
Most Desirable:
* ID Selector (`#id`): IDs are unique within a document, making them very specific and efficient for selecting a single element. Use them when you need to target a specific element with a guaranteed unique ID.
Less Desirable, But Good:
* Class Selector (`.class-name`): Classes can be applied to multiple elements, offering more flexibility than IDs. They are reusable and promote better code organization. Use them when you need to style a group of elements with the same characteristics.
Even Less Desirable, Use with Caution:
* Type Selector (`element-name`): These target all elements of a specific type (e.g., `p` for paragraphs). They can be slow and inflexible, especially for complex pages with many elements of the same type. Use them sparingly, and only when you absolutely need to target all elements of a specific type.
Least Desirable (Avoid if Possible):
* XPath: While XPath is powerful and can target almost any element, it's complex, slow for browsers to parse, and can become brittle if the HTML structure changes. It's generally recommended to avoid XPath unless there's absolutely no other way to achieve what you need.
Here's why this order is preferred:
* Specificity: More specific selectors (ID > Class > Type) take precedence over less specific ones in case of conflicting styles. This makes your code more predictable and easier to maintain.
* Performance: Browsers can process simpler selectors (ID, Class) faster than complex ones (XPath).
* Maintainability: Using IDs and Classes makes your code more readable and easier to update if the HTML structure changes. Relying on fragile selectors like XPath makes maintenance difficult.
In summary:
* Aim for ID selectors when targeting unique elements.
* Use class selectors for reusable styles on multiple elements.
* Use type selectors cautiously and only when necessary.
* Avoid XPath unless absolutely essential.
Thanks so much. This is a great summarization and exactly what I needed.
Hi Raghav. Thanks so much for your tutorials. I have been making presentations during sprint reviews and I would appreciate it very much if you don’t mind sharing with me the tool you use to draw the rectangular shapes around the texts on the screen. Thank you.
Eddie, its mac screen brush
So useful!!! Thanks a lot
Glad it was helpful!
Very useful session, thanks a lot.
Most welcome!
Hi @RaghavPal, your lessons and explanations are really great. But on the official site of Playwright about Locators, it is recommended to use built-in locators rather than css and xpath. So is it possible to add a lesson on how we can use built-in-locators manually in addition to this lesson? Thanks in advance 🙏
Alp
Playwright provides a robust set of built-in locators that enhance test reliability and maintainability. Let's delve into how you can manually use these locators to locate elements on a page.
1. By Role (Recommended):
- The `page.getByRole()` locator is based on how users and assistive technology perceive the page. It's particularly useful for locating elements like buttons, checkboxes, headings, links, and more.
- To use it, pass the accessible name (usually the text associated with the element) along with the role. For instance:
```javascript
await page.getByRole('button', { name: 'Sign in' }).click();
```
- You can also use regular expressions for matching names:
```javascript
await page.getByRole('button', { name: /submit/i }).click();
```
2. By Text Content:
- Use `page.getByText()` to locate elements based on their visible text content. For example:
```javascript
await expect(page.getByText('Welcome, John!')).toBeVisible();
```
3. By Label:
- To locate form controls by their associated label's text, use `page.getByLabel()`. Example:
```javascript
await page.getByLabel('User Name').fill('John');
```
4. By Placeholder:
- Use `page.getByPlaceholder()` to locate an input element by its placeholder text.
5. By Alt Text:
- Locate elements (usually images) by their alternative text using `page.getByAltText()`.
6. By Title Attribute:
- Use `page.getByTitle()` to locate an element by its `title` attribute.
7. By Test ID:
- If your elements have custom `data-testid` attributes, you can use `page.getByTestId()` to locate them.
Remember, prioritize user-facing attributes and explicit contracts like `page.getByRole()` for resilient tests. You can chain these locators to iteratively narrow down your search. For instance:
```javascript
const locator = page.getByRole('button', { name: 'Sign in' });
await locator.hover();
await locator.click();
```
@@RaghavPalThank you very much for your valuable explanations🎯. But still, it would be great to see a video (lesson) that covers these topics with your unique explanation 🙏
Awesome tutorial series. Question: Has Explore feature on Playwright Inspector been deprecated? I just downloaded on Mac and don't have the option.
As of the latest version of Playwright Inspector (1.17.0), the Explore feature has been moved to a separate standalone tool called Playwright Inspector DevTools extension. You can install the Playwright Inspector DevTools extension from the Chrome Web Store and use it to explore and interact with elements on your webpage.
Make sure to update to the latest version to access this feature.
and how to see what is happen during open pdf file uploaded on web page in backend on playwright?
To see what happens during opening a PDF file uploaded on a web page in the backend on Playwright, you can use the following steps:
1. Open the Playwright browser that you want to use for testing.
2. Navigate to the web page where you can upload PDF files.
3. Upload a PDF file to the web page.
4. Open the Developer Tools in the Playwright browser.
5. Go to the Network tab in the Developer Tools.
6. Click the Clear button to clear the network log.
7. Click the Record button to start recording the network traffic.
8. Click the link to open the uploaded PDF file.
9. Click the Stop button to stop recording the network traffic.
10. Inspect the network log to see what happens during opening the uploaded PDF file.
You can also use the Playwright `Network` class to inspect the network traffic. The `Network` class provides a variety of methods for getting information about the network requests and responses that are sent between the Playwright browser and the backend server.
Here is an example of how to use the `Network` class to inspect the network traffic during opening an uploaded PDF file:
```python
import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto('example.com/upload-pdf')
# Upload a PDF file.
await page.locator('[type="file"]').set_input_files('my-pdf.pdf')
await page.locator('[type="submit"]').click()
# Wait for the PDF file to be uploaded.
await page.wait_for_navigation()
# Open the uploaded PDF file.
await page.locator('[href="my-pdf.pdf"]').click()
# Get the network traffic.
network = page.network
traffic = await network.get_traffic()
# Inspect the network traffic.
for request in traffic:
print(request.url)
if __name__ == '__main__':
asyncio.run(main())
```
This code will print the URLs of all of the HTTP requests that are sent between the Playwright browser and the backend server during opening the uploaded PDF file.
I hope this helps
Hi Raghav, could you please cover how to handle dynamic web table in playwright with JavaScript? It would be great help. It's looking like no one covered this topic in JavaScript.
I will plan Ramu
@@RaghavPal : Thank you Raghav !!
@@RaghavPal I would be happy
@@RaghavPal Thanks 😊, i don't know what the topi is all about, but i'll love to get the link to the video :)
Hi Raghav
Firstly I want to say how useful these videos are as I am new to coding. Secondly, at 12:22 the object was identified and worked for me too but when i clicked on step over it didn't click in the username field but instead my inspector stopped. Can you please let me know what could be the reason.
Thanks
Glad to know these videos are helping you.. will need to check and troubleshoot this.. try some other scenarios and check
Hi Raghav, excellent tutorial - I am sharing your content wherever my contract is!! I notice that now the Playwright selectors web page is no longer there under the reference given - wonder why it has gone in last 3 months?
Thanks a lot, I will check on this, if I find major changes will add updated sessions
My score 5/5. thank
Great score Anto.. keep it up
urwelcome 🙏@@RaghavPal
Hi Raghav. How do we handle dynamic changing IDs? Can you please do a tutorial
I will check and plan on this Sindhura
HI Raghav, for css selector do we need to give # before the locator? for ex: login-button is the locator #login-button
Sirisha
Yes, you need to give a # before the locator if you are using a CSS ID selector. A CSS ID selector is a unique identifier for an element on a page. To select an element using a CSS ID selector, you use the following syntax:
```
#id-of-element
```
For example, to select the element with the ID `login-button`, you would use the following selector:
```
#login-button
```
You do not need to give a # before the locator if you are using a different type of CSS selector, such as a class selector or a tag selector.
Here are some examples of other CSS selectors:
```
.class-of-element
```
```
tag-name
```
```
tag-name.class-of-element
```
```
tag-name:nth-child(n)
```
```
tag-name:hover
```
```
tag-name:active
```
You can learn more about CSS selectors in the following documentation:
* CSS Selectors: developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors
I hope this helps
Also can you please touch on how to locate objects on modal content or popups
I will plan Satya
how to select test time out from config.js if timeout not exist in config.js file?
To select test time out from config.js if timeout does not exist in config.js file using Playwright, you can use the following code:
```javascript
const config = require('./config.js');
// Get the test timeout from config.js, or use a default value of 10000 milliseconds (10 seconds) if timeout does not exist in config.js.
const testTimeout = config.timeout || 10000;
// Set the test timeout for Playwright.
test.setTimeout(testTimeout);
```
This code will first check if the `timeout` property exists in the `config.js` file. If it does, the code will use the value of the `timeout` property as the test timeout. If the `timeout` property does not exist in the `config.js` file, the code will use a default value of 10000 milliseconds (10 seconds) as the test timeout.
Here is an example of how to use the above code in a Playwright test:
```javascript
const config = require('./config.js');
// Get the test timeout from config.js, or use a default value of 10000 milliseconds (10 seconds) if timeout does not exist in config.js.
const testTimeout = config.timeout || 10000;
// Set the test timeout for Playwright.
test.setTimeout(testTimeout);
test('should open the Google homepage', async () => {
const browser = await test.newBrowser();
const page = await browser.newPage();
await page.goto('www.google.com/');
// Assert that the Google homepage is open.
expect(await page.title()).toBe('Google');
await browser.close();
});
```
If the `timeout` property does not exist in the `config.js` file, the above test will have a timeout of 10 seconds.
@@RaghavPal where can I write this code?
in config.js file or what?
thank you very much for your interest to reply on my question
how do you select a nested text? like
Hi
I want to verify that the text Hi is there but the is not allowing me to
Hi, In Appium, you can use the "findElement" method and the "xpath" locator to select a nested text element like the one you described
Here is an example
/*
WebElement element = driver.findElement(By.xpath("//div[@class='errors']/b"));
String text = element.getText();
*/
This code will locate the element that is nested inside the element, and then extract the text content of the element using the getText() method
I just want to know do you also have tutorials in API testing
Hi Nomandla
For Playwright API Testing, I need to create, but there are other API Testing videos, Can check the section here - automationstepbystep.com/
I am stuck at scenario like if you have 5 images and each image has header and link, want to cover in a single iteration.please help me on this
Dev
Let's break down the problem step by step
Problem Statement:
You have 5 images on a webpage, each with a header and a link. You want to automate testing using Playwright to cover all 5 images in a single iteration.
Step 1: Inspect the HTML structure
Open the webpage in a browser and inspect the HTML structure of the images using the developer tools. Identify the common CSS selectors or XPath expressions that can be used to locate all 5 images.
For example, let's assume the HTML structure is:
```html
Header 1
Link 1
Header 2
Link 2
```
In this case, we can use the CSS selector `.image-container` to locate all 5 images.
Step 2: Use Playwright to locate all images
In your Playwright script, use the `page.$$` method to locate all elements that match the CSS selector `.image-container`. This will return an array of elements.
```javascript
const images = await page.$$('.image-container');
```
Step 3: Iterate over the images and extract header and link text
Use a `for` loop to iterate over the `images` array and extract the header and link text for each image. You can use the `element.querySelector` method to locate the header and link elements within each image container.
```javascript
for (const image of images) {
const header = await image.querySelector('h2');
const link = await image.querySelector('a');
const headerText = await header.textContent();
const linkText = await link.textContent();
const linkHref = await link.getAttribute('href');
// Do something with the extracted data, e.g., log it to the console
console.log(`Image Header: ${headerText}, Link: ${linkText} (${linkHref})`);
}
```
Step 4: Verify the extracted data (optional)
If you want to verify that the extracted data is correct, you can add additional assertions or checks within the loop.
That's it! With these steps, you should be able to cover all 5 images in a single iteration using Playwright.
Thank you for your lecture.
I've test many times, under line
await page.click('id="user-name"')
but debug window's 'step over' and other buttons are disabled at this line.
so I change like this
await page.click('[id="user-name"]')
it is worked.
Could you check this please?
Hi, if working, this is fine,
Hi sir could you please help me to solve the issue in playwright with js i have requirements like if I have to create some data on web ui and then I have to click save as button on web ui.if i click on save as the desktop save as window will open there i can edit file name and click on save button to save the ui data in local.but i don't have input file option to do with playwright . Could you help me to solve this issue .
Sanjeev
It seems you want to automate the process of saving data from a web UI as a local file using Playwright. Unfortunately, Playwright doesn't directly support the "Save As" dialog for web pages. However, I can suggest a couple of workarounds:
1. Print to PDF:
- You can emulate the "Save as PDF" functionality by printing the web page to a PDF directly from Playwright.
- Here's an example in Python:
```python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("your_url_here")
# Emulate print media type
await page.emulate_media("print")
# Generate PDF
await page.pdf(path="output.pdf", format="A4")
browser.close()
```
- Adjust the URL and file path as needed.
2. Keyboard Shortcuts:
- If the "Save as" option is accessible via keyboard shortcuts (e.g., Ctrl + S), you can simulate those key presses using Playwright.
- First, focus on the desired element (e.g., the web page content).
- Then, send the keys for the shortcut (e.g., Shift + F10, arrow keys, and Enter) to trigger the "Save as" action
Remember to adapt these solutions to your specific use case. If neither of these options works for your scenario, consider exploring other automation tools or libraries that might better suit your needs. Good luck
-
Can we do automation testing by playwright on a Flutter web page?
Hi Rushikesh
Yes, you can do automation testing by Playwright on a Flutter web page
Hi Raghav, thanks for the series. Can you please help me in the following. When I am trying to get the dropdown options using the following code, I am getting null and undefined values on lines 1 & 2 respectively. Plese help here.
const state=await page.$('#state');
const stateoptions=await state.$$('option');
Sravanthi
Let's address the issue you're facing.
1. Getting the Selected Option Value:
- To get the selected option value from a dropdown, you can use the following code:
```javascript
const selectedValue = await page.$eval('#state', sel => sel.value);
console.log('Selected value:', selectedValue);
```
- Replace `#state` with the actual selector for your dropdown element. This code will return the value of the currently selected option.
2. Getting the Selected Option Text:
- To get the text of the selected option, you can use:
```javascript
const selectedText = await page.$eval('#state', sel => sel.options[sel.selectedIndex].textContent);
console.log('Selected text:', selectedText);
```
- Again, replace `#state` with your actual selector. This code retrieves the text content of the currently selected option.
3. Complete Example:
- Here's how you can combine both approaches:
```javascript
const state = await page.$('#state');
const selectedValue = await page.$eval('#state', sel => sel.value);
const selectedText = await page.$eval('#state', sel => sel.options[sel.selectedIndex].textContent);
console.log('Selected value:', selectedValue);
console.log('Selected text:', selectedText);
```
- Make sure to adjust the selector (`#state`) to match your specific dropdown element.
Remember to replace `#state` with the actual selector for your dropdown
@@RaghavPal Thank you so much Raghav. I learnt couple of new things from your comment now. Trying with the following code, I am able to now get the whole list of dropdown options(static one). But why am I seeing the error message "Object possibly null" here (at the code, on mousehover) but finally it works fine. Confused in this point. Can you pl explain in brief.
await(await (await page.$("#state")).$$("option")).forEach(async o=>console.log(await o.textContent() as unknown as string));
Let's break down the code snippet you provided and address the points of confusion:
1. Getting Dropdown Options:
- The code you shared aims to retrieve the text content of all `` elements within a dropdown (select) element with the ID `"state"`.
- The `await page.$("#state")` part selects the dropdown element.
- The `await (await page.$("#state")).$$("option")` part selects all `` elements within the dropdown.
- Finally, the `.forEach(async o => console.log(await o.textContent() as unknown as string))` loop iterates through each option and logs its text content.
2. "Object Possibly Null" Error:
- The error message "Object possibly null" occurs because TypeScript (or JavaScript) is warning you that the result of `await page.$("#state")` could be `null`.
- This warning is due to the possibility that the element with the ID `"state"` might not exist on the page.
- When you use `await` with `page.$("#state")`, it returns a `null` value if the element is not found.
- To avoid this warning, you can add a null check before accessing the options:
```javascript
const dropdown = await page.$("#state");
if (dropdown) {
const options = await dropdown.$$("option");
options.forEach(async o => console.log(await o.textContent() as unknown as string));
}
```
3. Why It Works Fine Anyway:
- Despite the warning, your code works because Playwright handles the `null` case gracefully.
- If the element is not found, the `await page.$("#state")` expression resolves to `null`, and subsequent operations (such as `.forEach`) are simply skipped.
- So, even though TypeScript warns you about the possibility of `null`, Playwright ensures that the code doesn't break.
4. Best Practice:
- To improve readability and avoid the warning, consider using a null check as shown above.
- Additionally, you can handle any specific logic (e.g., error handling) if the element is not found.
Remember that TypeScript's static analysis helps catch potential issues early, but in this case, Playwright's runtime behavior ensures that your code works as expected
---
@@RaghavPal Thank you so so much Raghav for such a detailed explanation. Love to watch your videos always which targets on the pin pointed explanation within short duration. Thanks once again.
how to see what happen during uploading to pdf files to my web app in backend?
Moataz
To see what happens during uploading to PDF files to your web app in the backend, you can use a variety of tools and techniques.
One way to see what happens during uploading is to use a network capture tool, such as Wireshark or Fiddler.
Another way to see what happens during uploading is to use a debugger, such as Visual Studio Code or IntelliJ IDEA.
Finally, you can also use the logging features of your backend server to see what happens during uploading. For example, you can log the names of the uploaded files, the sizes of the uploaded files, and the timestamps of the uploaded files. This information can be useful for troubleshooting problems with uploading PDF files.
Here are some specific steps that you can take to see what happens during uploading to PDF files to your web app in the backend:
1. Open a network capture tool, such as Wireshark or Fiddler.
2. Start the network capture tool.
3. Upload a PDF file to your web app.
4. Stop the network capture tool.
5. Analyze the network traffic to identify the specific HTTP requests that are used to upload PDF files to the backend.
6. Open a debugger and attach it to the backend server.
7. Set a breakpoint at the beginning of the code that is used to process uploaded PDF files.
8. Upload a PDF file to your web app.
9. Step through the code in the debugger to see what happens during uploading.
10. Enable logging on the backend server.
11. Upload a PDF file to your web app.
12. Check the logs to see what information is logged about the uploaded file.
I hope this helps
in my code i insert
var hrefs = await page.evaluate(() => {
return Array.from(document.links).map(item => item.href);
});
but i have different result with or without --header
how can i solve this?
Hi Almanacco,
If you are seeing different results when using the --header option in Playwright, it is possible that the server you are interacting with is returning different content based on the headers that are sent with the request.
When you use the --header option, you are specifying additional headers to be sent with the request. If the server is checking for the presence of certain headers, or if it is using the headers to determine the response that is sent, then the results could be different.
One way to solve this would be to investigate what headers the server is expecting, and make sure that you are sending the correct headers with your request. You can inspect the requests being sent by using the browser's built-in developer tools, or by using a tool like Wireshark to inspect the network traffic.
Another approach would be to try to make the request without the --header option and inspect the response to see if there are any clues about what headers are needed. You could then try adding those headers to your request using Playwright's setExtraHTTPHeaders method.
For example, you could try something like this:
//javascript
await page.setExtraHTTPHeaders({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
});
var hrefs = await page.evaluate(() => {
return Array.from(document.links).map(item => item.href);
});
This sets the "User-Agent" header to the same value that is sent by Chrome, which may help to make the request look more like it is coming from a real browser
Why we find web objects manually when we have test recorder ?
Hi Rohan
Yes, In Playwright, you have the option to use the Test Recorder to automatically generate code by interacting with the web application. However, knowledge of manual process will also be handy in some scenarios
1. Complex Scenarios: The Test Recorder may not capture all the interactions or scenarios you need to test. In complex test cases, you may have to manually find and interact with specific elements that are not covered by the Test Recorder.
2. Customization and Flexibility: Manual identification allows you to fine-tune your element selection based on specific attributes or conditions that are not captured by the Test Recorder. You can use custom selectors or additional properties to locate elements precisely as per your requirements.
3. Dynamic Elements: In dynamic web applications, elements may have dynamic IDs, classes, or attributes that are not consistently predictable. Manually finding elements allows you to adapt to such changes and handle dynamic elements more effectively.
4. Code Reusability: Manually locating elements allows you to create reusable functions or methods for interacting with specific elements across multiple tests or test cases. This promotes code modularity and makes maintenance easier.
5. Non-UI Testing: Not all tests involve direct interaction with the UI. Some tests may require accessing backend APIs, database validations, or other non-UI related tasks. In such cases, manual element identification is necessary to test these non-UI components.
It's important to note that the Test Recorder can be a valuable starting point for creating your tests, especially for simple scenarios or when you're new to Playwright. However, as your test cases become more complex and require advanced interactions, you may find the need to manually locate elements to achieve the desired level of control and flexibility
Score is 5.
Great, best wishes for next Sagarika
Hi Raghav, how we can disable the incognito window in playwright?? Chrome
Hi Giridhar, this can help stackoverflow.com/questions/71626466/python-playwright-how-to-start-in-non-incognito-mode
Hi Raghav, my application has lot of drop downs, radio button and checkboxes how to select a value from them?
Sirisha
To select a value from drop-downs, radio buttons, and checkboxes using Playwright, you can use the following methods:
Drop-downs: Use the selectOption() method to select an option from a drop-down. Here is an example:
await page.selectOption('#myDropdown', { value: 'optionValue' });
Radio buttons: Use the click() method to select a radio button. Here is an example:
await page.click('#myRadioButton');
Checkboxes: Use the click() method to toggle the state of a checkbox. Here is an example:
await page.click('#myCheckbox');
Note that you need to provide the correct selector for each element to interact with it using Playwright. Also, make sure that the element is visible and enabled before interacting with it. You can use the waitForSelector() method to ensure that the element is ready to be interacted with.
@@RaghavPal Thanks i will try but would you be able to make a video for us.
i will plan
I couldn't find 'Explore' button in the Playwright Inspector on my Mac
Santhosh
It may be due to version issue, Please check the latest documentation from Playwright
@@RaghavPal Can you please let me know the version you have used in this video?
How to capture this error message from this "alert error" class ? Playwright is unable to locate this. I've tried xpath, css and other locator options...
Your account is invalid or not active. Please contact us for help.
Hi Raja,
In Playwright, you can capture the error message from an "alert error" class by using the page.waitForSelector method and then getting the text content of the selected element.
Eg:
const element = await page.waitForSelector('.alert.error');
const errorMessage = await page.evaluate(element => element.textContent, element);
console.log(errorMessage);
@@RaghavPal Thank you. this fixed my issues. Do you have any videos regarding integrations between Playwright framework and TestRails ? If no videos, any recommendations ? Thanks.
Not yet
is it possible to click using the screenshot.png selector?
No, it is not possible to click using the screenshot.png selector in Playwright. The screenshot.png selector is a visual selector that allows you to identify an element by its appearance in a screenshot. It is primarily used for debugging and troubleshooting purposes.
hi Raqhav, how do you automate a hamburger button or a menu in the playwright
Sirisha
To automate a hamburger button or a menu in Playwright, you can use the following steps:
1. Locate the hamburger button or menu element. You can use the `Locator` class to locate the element by its CSS selector, XPath, or other selector.
2. Click on the hamburger button or menu element. You can use the `Locator.click()` method to click on the element.
3. Wait for the menu to open. You can use the `Locator.waitFor()` method to wait for the menu to open.
4. Interact with the menu items. You can use the `Locator` class to locate the menu items and interact with them using the `Locator.click()`, `Locator.hover()`, and other methods.
Here is an example of a Playwright script that automates a hamburger button and menu:
```javascript
const { test, expect } = require('@playwright/test');
test('Automate hamburger button and menu', async ({ page }) => {
// Locate the hamburger button element.
const hamburgerButton = page.locator('.hamburger-button');
// Click on the hamburger button.
await hamburgerButton.click();
// Wait for the menu to open.
await page.waitForSelector('.menu');
// Locate the menu items.
const menuItems = page.locator('.menu-item');
// Click on the first menu item.
await menuItems.first().click();
// Assert that the first menu item is selected.
await expect(menuItems.first()).toBeChecked();
});
```
You can modify this script to automate the specific hamburger button or menu that you are working with.
@@RaghavPal Thanks Raghav i really appreciate the help for the detailed code but in my application the Hamburger menu - hides and opens the left nav
there is no drop down but how it is is click on the left nav it Expands the left nav and collapses the left nav need to automate that using playwright but am getting errors that target closed and not ale to find locators. I feel that i have written up the correct xpath but trying my best in various ways to solve it.
Here are some things to try when automating a left nav that hides and opens using Playwright:
1. Check the HTML and CSS of the left nav to make sure you have the correct locator.
2. Try using a different locator, such as a CSS selector or a text selector.
3. Try using the `frame()` method to switch to the frame that contains the left nav.
4. Try using the `waitForNavigation()` method to wait for the page to navigate after clicking on the left nav.
5. Try using the `evaluate()` method to evaluate JavaScript on the page.
Here is an example of how to use the `evaluate()` method to automate a left nav that hides and opens using Playwright:
```
import { test, expect } from '@playwright/test';
test('Automate hidden left nav', async ({ page }) => {
// Wait for the left nav to be visible.
await page.waitForSelector('.left-nav');
// Evaluate JavaScript on the page to expand the left nav.
await page.evaluate(() => {
document.querySelector('.left-nav').classList.add('expanded');
});
// Wait for the left nav to be expanded.
await page.waitForSelector('.left-nav.expanded');
// Evaluate JavaScript on the page to collapse the left nav.
await page.evaluate(() => {
document.querySelector('.left-nav').classList.remove('expanded');
});
// Wait for the left nav to be collapsed.
await page.waitForSelector('.left-nav:not(.expanded)');
});
```
You can also try using a third-party library to automate the left nav. For example, the `Playwright Extras` library includes a `LeftNav` class that can help you automate left navs.
I hope this helps
@@RaghavPal awesome Thanks so much raghav it worked! this is a huge help
sir ye mere VS mein work hi nahi karta
will need to see the logs or message Akash, Can try using a new version of VS code
How is it possible to click on the "Login" button twice? await page.locator('text=LOGIN').click() await page.locator('input:has-text("LOGIN")').click()
To click the "Login" button twice using Playwright, you can use the `click()` method on the same locator twice. However, your current code uses two different locators. If you want to click the same button twice, you should use the same locator both times. Here's how you can do it:
```javascript
// Click the "Login" button twice using the same locator
await page.locator('text=LOGIN').click();
await page.locator('text=LOGIN').click();
```
Alternatively, if you need to ensure a delay between the two clicks, you can add a `waitForTimeout` between the clicks:
```javascript
// Click the "Login" button twice with a delay
await page.locator('text=LOGIN').click();
await page.waitForTimeout(1000); // Wait for 1 second
await page.locator('text=LOGIN').click();
```
If you specifically need to use different locators for some reason, ensure both locators correctly identify the same "Login" button:
```javascript
// Click the "Login" button twice using different locators
await page.locator('text=LOGIN').click();
await page.locator('input:has-text("LOGIN")').click();
```
Make sure the locators you use correctly identify the "Login" button on your page.
-
@@RaghavPal Thank you for your answer. Yes, I'm using two different locators of one element - the "Login" button as in the video. The question is: how can you click on the same button twice? After clicking the "Login" button once, the next page should open and the "Login" button shouldn't be available for the second click. In this video there are two lines of code clicking the "Login" button
okay i will check.. can let me know the timestamp in the video
@@RaghavPal 31:21 lines of code 18,19. But now I see that it works as expected. There was no command to enter a password so you could click on the "Login" button two or more times. It was my mistake
When I run my test with this command "npx playwright test .\tests\myfirst.spec.js --headed", I get the error no test found but test would run successfully when I run with "npx playwright test myfirst.spec.js --headed"
Faith
The reason why you are getting the "No tests found" error when you run the command `npx playwright test .\tests\myfirst.spec.js --headed` is because the Playwright test runner is looking for test files in the current directory. When you specify the path to the test file, the Playwright test runner is not able to find the file because it is not in the current directory.
However, when you run the command `npx playwright test myfirst.spec.js --headed`, the Playwright test runner is able to find the test file because you are not specifying the path to the test file.
To fix this, you need to make sure that the test file is in the current directory. You can do this by moving the test file to the current directory or by using the `cd` command to change to the directory where the test file is located.
For example, if the test file is located in the `tests` directory, you can run the following command to change to the `tests` directory:
```
cd tests
```
Once you are in the `tests` directory, you can run the command `npx playwright test myfirst.spec.js --headed` and the Playwright test runner will be able to find the test file.
Another reason why you might be getting the "No tests found" error is because the test file does not contain any tests. A test file must contain at least one test function. If the test file does not contain any test functions, the Playwright test runner will not be able to find any tests.
To fix this, you need to add a test function to the test file. A test function is a function that starts with the `test` keyword. For example, the following is a valid test function:
```
test("My first test", () => {
// Your test code goes here
});
```
Once you have added a test function to the test file, you should be able to run the test file without getting the "No tests found" error.
I hope this helps