How to solve selenium webdriver: ElementNotInteractableError: element not interactable in nodejs - node.js

I started to learn Selenium
but i'm stuck trying to upload and download on a element like this:
I want to upload a dwg file on this site and convert it into a text file. So I'm using selenium.
I encountered a problem while uploading the file
This is my error message:
We have tried several solutions to this problem.
ADD driver.manage().window().maximize();
use click() instead of sendKeys()
Check Element is Enabled
However, no solution has solved the problem.
This is the entire code:
const { Builder, Browser, By, Key, until } = require("selenium-webdriver");
const chromeDriver = require("selenium-webdriver/chrome");
const chromeOptions = new chromeDriver.Options();
const chromeExample = async () => {
const driver = await new Builder()
.forBrowser(Browser.CHROME)
.setChromeOptions(chromeOptions.headless())
.build();
driver.manage().window().maximize();
await driver.get("https://products.aspose.app/cad/text-extractor/dwg");
await driver.wait(
until.elementLocated(By.className("filedrop-container width-for-mobile")),
10 * 1000
);
await driver.wait(
until.elementIsEnabled(
driver.findElement(By.className("filedrop-container width-for-mobile"))
),
10 * 1000
);
const tmp = await driver
.findElement(By.className("filedrop-container width-for-mobile"))
.sendKeys("/home/yeongori/workspace/Engineering-data-search-service/macro/public/images/testfile1.dwg");
console.log(tmp);
};
The same error occurs when i change the code as below.
await driver
.findElement(By.className("filedrop-container width-for-mobile"))
.sendKeys(Key.ENTER);
One strange thing is that if i change sendKeys to click and check tmp with console.log, it is null.
This is Project Directory
How can I solve this problem? I'm sorry if it's too basic a question. But I'd be happy if there was any hint. Thank you.
WSL2(Ubuntu-20.04), Node.js v18.12.1

You need to use sendKeys on the input element which is nested deeper in the element that you are currently trying to send keys to.
You can reach the element with this xpath:
"//*[contains(#id,'UploadFileInput')]"

Related

Why webdriverio can't find element?

await this.browser.url(url);
await this.browser.pause(5000);
const link = await $('a');
It opens the URL but after a pause I get the following error:
TypeError: Cannot read property 'isDevTools' of undefined
how to fix this?
Just need to use $ as browser object funtion
const link = await this.browser.$('a');
For anyone else seeing this issue, I later realized I was importing the $ command from the package, which was not correct. It was added without my knowledge – I think VS Code auto-imported while writing more tests.
import $ from 'webdriverio/build/commands/browser/$'; <<-- Removed this and it worked fine.
describe('Connect Apps / Manage Apps', async () => {
before(async () => {
const elem = await $('.results');
await elem.waitForDisplayed(5000, true);
});

Playwright: Upload files from non-input element that cannot be used page.setInputFiles?

I'm working on uploading files through non-input HTML tag on Playwright.
For example, you can use setInputFiles like this, and this works:
await page.setInputFiles('input[type="file"]', './headphone.png')
But apparently setInputFiles only works for input element, something like this will be error:
await page.setInputFiles('label.ImageUpload__label ', './headphone.png');
The HTML I'm working on is like this:
<div id="ImageUpload" class="ImageUpload u-marginB10">
<label class="ImageUpload__label js-dragdrop-area" for="selectFileMultiple">
<span class="ImageUpload__hide">drag and drop or select files</span>
<span class="ImageUpload__text"><span class="js-dragdrop-num">10</span>up to</span>
</label>
</div>
So, is it possible to upload files to such HTML elements with Playwright?
NodeJs: https://playwright.dev/python/docs/api/class-filechooser
page.on("filechooser", (fileChooser: FileChooser) => {
fileChooser.setFiles(["/path/to/a/file"]);
})
Python: https://playwright.dev/python/docs/api/class-filechooser/
with page.expect_file_chooser() as fc_info:
page.click("upload")
file_chooser = fc_info.value
file_chooser.set_files("/path/to/a/file")
Java: https://playwright.dev/java/docs/api/class-filechooser
FileChooser fileChooser = page.waitForFileChooser(() ->
page.click("upload"));
fileChooser.setFiles(Paths.get("myfile.pdf"));
To upload a file using Playwright use setInputFiles(selector, files[, options]) function. This method takes the selector of the input element and the path to the file you want to upload.
The files parameter value can be a relative path (relative to the current working directory) or an absolute path. I strongly suggest that you use an absolute path to ensure predictable behavior.
test("upload a file", async ({ page }) => {
console.log(resolve(__dirname, "bar.png"));
await page.goto("http://127.0.0.1:8080/upload-file/");
await page.locator('input[name="foo"]').click();
await page
.locator('input[name="foo"]')
.setInputFiles(resolve(__dirname, "bar.png"));
await page.click("input[type=submit]");
});
Alternatively, you can read the file into a Buffer and dispatch drop event onto the target element with DataTransfer payload. This is useful when you are testing a drag-and-drop area:
const dataTransfer = await page.evaluateHandle(
async ({ fileHex, localFileName, localFileType }) => {
const dataTransfer = new DataTransfer();
dataTransfer.items.add(
new File([fileHex], localFileName, { type: localFileType })
);
return dataTransfer;
},
{
fileHex: (await readFile(resolve(__dirname, "bar.png"))).toString("hex"),
localFileName: fileName,
localFileType: fileType,
}
);
await page.dispatchEvent("#drop_zone", "drop", { dataTransfer });
await expect(page.locator("text=bar.png")).toBeVisible();
You can further simplify the above code using createDataTransfer utility from playwright-utilities:
const dataTransfer = await createDataTransfer({
page,
filePath: resolve(__dirname, "bar.png"),
fileName: "bar.png",
fileType: "image/png",
});
await page.dispatchEvent("#drop_zone", "drop", { dataTransfer });
await expect(page.locator("text=bar.png")).toBeVisible();
Try this example locally by cloning the Playwright Playground repository:
git clone --branch test/upload-file https://punkpeye#github.com/punkpeye/playwright-playground.git
cd playwright-playground
npm install
npx playwright test tests/upload-file
Found another alternative to upload that worked in my case. We create a buffer from memory and drag and drop the file to the upload button.
// Read your file into a buffer.
const buffer = readFileSync('file.pdf');
// Create the DataTransfer and File
const dataTransfer = await scope.page.evaluateHandle((data) => {
const dt = new DataTransfer();
// Convert the buffer to a hex array
const file = new File([data.toString('hex')], 'file.pdf', { type: 'application/pdf' });
dt.items.add(file);
return dt;
}, buffer);
// Now dispatch
await page.dispatchEvent('YOUR_TARGET_SELECTOR', 'drop', { dataTransfer });
if using typescript, add this to the top of the file:
import {readFileSync} from 'fs';
Github issue: https://github.com/microsoft/playwright/issues/10667#issuecomment-998397241
I had the same issue so I decided to use AutoIt to upload files with Playwright.
AutoIt v3 is a freeware BASIC-like scripting language designed for automating Windows GUI and general scripting.
I used AutoIT to handle the Windows File Upload dialog, which cannot be handled using Playwright.
Creating Script
Download AutoIt: https://www.autoitscript.com/site/autoit/downloads/
Open SciTE Script Editor and type the followng:
WinWaitActive("Choose files")
Send("C:\ChromeDriver\text.txt")
Send("{ENTER}")
If it does not work, change Choose files to whatever title is on the top left of the upload dialog.
Click save and name it something like upload.au3 and save it in the root directory of your test.
Example of Save Location
Right click your newly created file and click Compile Script
Executing the script in your test
Create execFile function of child process modules in node.js. Reference: https://nodejs.org/api/child_process.html#child_process_child_process_execfile_file_args_options_callback
Add this to the top of your .spec.ts test file:
var exec = require('child_process').execFile;
var upload_script = function(){
exec('upload.exe', function(err, data) {
console.log(err)
});
}
Open the upload dialog, then call the function in your test
// Click Browse
await page.locator('#browse').click();
// Execute Upload Script
upload_script();
You have to run your test headed or it will not work:
npx playwright test --headed

NoSuchElement: Unable to locate element

I tried to find element in my webpage using findElement() function. But i got the following error -
DevTools listening on ws://127.0.0.1:12127/devtools/browser/92800bba-de09-487a-93c4-61053590a4a2
(node:4944) UnhandledPromiseRejectionWarning: NoSuchElementError: no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id="captchaimg"]"}
After that i thought maybe its because of asynchronous way of execution, so tried using wait() function but the error remains.
Code -
var webdriver = require('selenium-webdriver');
var driver = new webdriver.Builder().withCapabilities(webdriver.Capabilities.chrome()).build();
driver.get("https://www.imsnsit.org/imsnsit/student.htm");
driver.wait(webdriver.until.elementLocated({xpath: '//*[#id="captchaimg"]'}));
var img = driver.findElement({xpath: '//*[#id="captchaimg"]'});
var link = img.getAttribute('src');
console.log(link);
Thanks in advance

How can I use exported strings as my elements in Puppeteer

I can't seem to declare a string const and use that as my element with Puppeteer. For example:
await page.click("#playerView");
Works fine, but:
const playerViewId = "#playerView";
await page.click(playerViewId);
Doesn't. I ultimately want to hold all my Page Elements in an object in a separate file to tidy up my project.
Any ideas why this isn't working?
Thanks
I can confirm that the following case does in fact work:
const playerViewId = '#playerView';
await page.click(playerViewId);
If this is not working, consider upgrading your version of Node.js and/or Puppeteer.
If you are trying to define your variable in a separate file, you can use:
// external-file.js:
module.exports.playerViewId = '#playerView';
// main-file.js:
const external_variables = require('./external-file');
const playerViewId = external_variables.playerViewId;
await page.click(playerViewId);
Additionally, you should check to make sure that the element with id playerView exists and has loaded completely before attempting to use page.click().

selinium-webdriver issue with Error: The geckodriver.exe executable could not be found on the current PATH

Hey I want to get screen shot with nodejs selinium-webdriver firefox
I am getting error like that : Error: The geckodriver.exe executable could not be found on the current PATH.
I set up the enviornment variable, but no luck
You need to set the path to the geckodriver.exe prior to creating the driver instance.
In Java:
System.setProperty("webdriver.gecko.driver", "./drivers/geckodriver.exe");//"<PATH TO LOCATION>\\chromedriver.exe");
I had some successful result with this process:
1° - Check if your webdriver(geckodriver, chromedriver, etc.) is in the correct path (if you don't know how to do it, check the link, https://www.youtube.com/watch?v=fj0Ud16YJJw). I think this video is a little old, because in npm the code information is different, updated, but it also serves as instruction.
2°- I changed my type of license(in package.json) from “ISC” to “MIT”, you can do this manually. And for my surprise, this change made my code go well.
const webdriver = require("selenium-webdriver");
const firefox = require("selenium-webdriver/firefox");
const { Builder, Browser, By, Key, until } = require("selenium-webdriver");
async function example() {
let driver = await new Builder().forBrowser(Browser.FIREFOX).build();
try {
await driver.get("https://www.google.com/ncr");
await driver.findElement(By.name("q")).sendKeys("Selenium", Key.RETURN);
await driver.wait(until.titleIs("webdriver - Google Search"), 1000);
} finally {
await driver.quit();
}
}
example();
And here we have another link that goes to selenium webdriver dependency in npm website(https://www.npmjs.com/package/selenium-webdriver) for more information.

Resources