Node.js 在docker Seleniu#Hub、Selenium Node Chrome Debug和带有Mocha+的容器中运行测试时无法上载文件;SeleniumWebDriver(JS)

Node.js 在docker Seleniu#Hub、Selenium Node Chrome Debug和带有Mocha+的容器中运行测试时无法上载文件;SeleniumWebDriver(JS),node.js,docker,selenium-webdriver,mocha.js,Node.js,Docker,Selenium Webdriver,Mocha.js,我花了很多时间试验和使用谷歌,试图找到一个解决这个问题的办法,但我没有取得任何成功,我希望有人能够提供一些指导。这就是我的情况,我正在尝试使用docker容器在我公司的应用程序上运行javascript mocha selenium webdriver测试。除了无法上传文件外,我似乎一切正常。在尝试在docker环境中使用我的测试之前,我能够在本地服务器上使用它,并使用如下方法上载文件: const companyImage = process.cwd()+ '/img/back

我花了很多时间试验和使用谷歌,试图找到一个解决这个问题的办法,但我没有取得任何成功,我希望有人能够提供一些指导。这就是我的情况,我正在尝试使用docker容器在我公司的应用程序上运行javascript mocha selenium webdriver测试。除了无法上传文件外,我似乎一切正常。在尝试在docker环境中使用我的测试之前,我能够在本地服务器上使用它,并使用如下方法上载文件:

        const companyImage = process.cwd()+ '/img/backgroundmario.jpg';
        const companyImageElem = await driver.findElement(By.xpath("//div/input[@type='file']"));
        await companyImageElem.sendKeys(companyImage);
await driver.findElement(By.xpath("//input[@type='file']")).sendKeys(path.resolve(__dirname, companyImage));
但是,在使用docker容器时,我没有取得任何成功。我将img文件夹安装到selenium/node chrome调试容器中,该容器包含一个VNC查看器,我可以看到图像存在(并且我可以通过VNC查看器手动上传图像)。然而,尽管提供了许多不同的图像路径,但我似乎无法上传我的图像。出于某种原因,工作目录似乎来自我的测试容器,而不是我的节点chrome调试容器,但即使我将图像添加到测试容器,并使用它们也不上载的图像更改到我的测试容器目录的路径

下面是我在测试中使用的代码片段(它包括一些我通常不会包括的内容,特别是检查process.cwd()和process.env.PWD,因为我只是想看看路径是什么:

const {
   Builder,
   By,
   Key,
   until,
   webdriver,
   action
} = require('selenium-webdriver');
const mocha = require('mocha');
const chai = require("chai");
const chaiAsPromised = require("chai-as-promised");
const {
   makeUtilityBelt
} = require('./util')
chai.use(chaiAsPromised);
const fs = require('fs');
const expect = require('chai').expect;
const ciPassword = require('./envData').ciPassword;
const campManagerMail  = 'jdrzymala+companycreator@influential.co';
const campManagerName = 'companycreator';
const campManagerUsername = 'companycreator';
const legacy = "http://node-web-client";
const companyImage = '/opt/test/images/backgroundmario.jpg';
var currentDir = process.cwd();
var appFolder = process.env.PWD;
const {
   createLegacyAdmin,
   createLegacyResellerCompany,
   createLegacyBrandCompany,
   createLegacyAgencyCompany,
   createLegacyCampManager,
   createLegacyClient,
   createLegacyInfluencer
} = require('./legacyCreationQueries');
const {
   getEmailId,
   getUserEmailId,
   getRandom,
   verifyRandom,
   accountSetup
} = require('./sqlutil');

describe('Creates a Company of Each Type via the Legacy Dashboard', function () {
   this.timeout(1200000);
   this.slow(20000);
   let driver;
   let util;

   before(async function () {
       driver = new Builder().forBrowser('chrome').usingServer('http://selenium_hub:4444/wd/hub').build();
       util = makeUtilityBelt(driver);
       await createLegacyCampManager(campManagerName, campManagerUsername, campManagerMail);

   });
   afterEach(function () {
       let testCaseName = this.currentTest.title;
       let testCaseStatus = this.currentTest.state;
       if (testCaseStatus === 'failed') {
           driver.takeScreenshot().then((data) => {
               let screenshotPath = `./results/${testCaseName}.png`;
               console.log(`Saving Screenshot as: ${screenshotPath}`);
               fs.writeFileSync(screenshotPath, data, 'base64');
           });
       } 
   });
   after(function () {
       driver.quit();
   });
   describe('Load Legacy Corporate Site and Login to Legacy Dashboard', function () {

       it('Loads into the Legacy Dashboard Successfully', async function () {
           await driver.get(legacy);
           await driver.wait(until.elementLocated(By.xpath("//p[contains(text(),'Sign In')]"), 10000));
           await driver.sleep(3000);
           const emailElem = await driver.findElement(By.xpath("//input[@id='email']"));
           await util.sendKeys(emailElem, campManagerMail);
           const pwElem = await driver.findElement(By.xpath("//input[@id='password']"));
           await util.sendKeys(pwElem, ciPassword);
           await driver.findElement(By.xpath("//button[contains(text(),'Sign In')]")).click();
           await driver.wait(until.elementLocated(By.xpath("//div/ul[contains(@class, 'campaign-search-list')]"), 10000));
           await driver.wait(until.elementLocated(By.xpath("//ul[@class='menu']/li/a/span[contains(text(),'User Management')]"), 10000));
           await driver.sleep(5000);
           await console.log("Below is the Current Working Directory");
           await console.log(currentDir);
           await driver.sleep(3000);
           await console.log(appFolder);
           await driver.sleep(3000);
           await console.log("The above is the app folder");
           await driver.sleep(2000);
           const loginSuccessElem = await driver.findElement(By.xpath("//ul[@class='menu']/li/a/span[contains(text(),'User Management')]"));
           let loginSuccess = await loginSuccessElem.isDisplayed();
           await driver.sleep(3000);
           await expect(loginSuccess, 'Legacy Login Failed').to.be.true;
       });
   });
   describe('Creates a Reseller Company', function(){
       const companyName = 'Reseller Test Company';
       it('Navigates to Company Management and Begins Company Creation Process', async function(){
           await driver.wait(until.elementLocated(By.xpath("//ul[@class='menu']/li/a/span[contains(text(),'Company Management')]"), 10000));
           await driver.findElement(By.xpath("//ul[@class='menu']/li/a/span[contains(text(),'Company Management')]")).click();
           await driver.sleep(8000);
           await driver.wait(until.elementLocated(By.xpath("//h3[contains(text(),'Search Companies')]"), 10000));
           await driver.wait(until.elementLocated(By.xpath("//a[contains(text(),'+ Create Company')]"), 10000));
           await driver.sleep(8000);
           await driver.findElement(By.xpath("//a[contains(text(),'+ Create Company')]")).click();
           await driver.wait(until.elementLocated(By.xpath("//h3[contains(text(),'Create Company')]"), 10000));
           const companyCreationPageElem = await driver.findElement(By.xpath("//h3[contains(text(),'Create Company')]"));
           let companyCreationPage = await companyCreationPageElem.isDisplayed();
           await expect(companyCreationPage, 'Company Creation Page failed to Load').to.be.true;            
       });
       it('Fills in the required fields and creates New Reseller Company', async function(){            
           const companyDescription = 'This is a test description for a random test company blah blah blah';
           const companyAddress = '777 Lucky Lane';
           const companyCity = 'Las Vegas';
           const companyState = 'Nevada';
           const companyZip = '89104';
           const companyNameElem = await driver.findElement(By.xpath("//input[@label='Company Name']"));
           await util.sendKeys(companyNameElem, companyName);
           await driver.sleep(1000);
           const companyDescriptionElem = await driver.findElement(By.xpath("//textarea[@label='Company Description']"));
           await util.sendKeys(companyDescriptionElem, companyDescription);
           await driver.sleep(1000);
           const companyTypeElem = await driver.findElement(By.xpath("//select"));
           await companyTypeElem.click();
           await driver.wait(until.elementLocated(By.xpath("//select/option"), 10000));
           const companyTypeSelectElem = await driver.findElement(By.xpath("//select/option[@value='1']"));
           await companyTypeSelectElem.click();
           await driver.sleep(1000);
           const addressElem = await driver.findElement(By.xpath("//input[@label='Address']"));
           await util.sendKeys(addressElem, companyAddress);
           await driver.sleep(1000);
           const cityElem = await driver.findElement(By.xpath("//input[@label='City']"));
           await util.sendKeys(cityElem, companyCity);
           await driver.sleep(1000);
           const stateElem = await driver.findElement(By.xpath("//input[@label='State']"));
           await util.sendKeys(stateElem, companyState);
           await driver.sleep(1000);
           const zipElem = await driver.findElement(By.xpath("//input[@label='Zip Code']"));
           await util.sendKeys(zipElem, companyZip);
           await driver.sleep(1000);
           await driver.findElement(By.xpath("//input[@type='file']")).sendKeys(companyImage);
           await driver.sleep(1000);
           await driver.wait(until.elementLocated(By.xpath("//img[@class='image-preview']"), 10000));
           await driver.sleep(1000);
           const submitButtonElem = await driver.findElement(By.xpath("//button[contains(text(),'Submit')]"));
           await submitButtonElem.click();
           await driver.wait(until.elementLocated(By.xpath("//h3[contains(text(),'Company Actions')]"), 10000));
           await driver.wait(until.elementLocated(By.xpath("//p[@class='company-name']"), 10000));
           const companySuccessElem = await driver.findElement(By.xpath("//p[@class='company-name'][contains(text(),'"+companyName+"')]"));
           let companySuccess = await companySuccessElem.isDisplayed();
           await expect(companySuccess, 'Failed to Create New Company').to.be.true;
       });
   });
});

这是阻止我将大量测试文件与我们的CI/CD流程集成的最后一件事,但我的大量测试涉及上传文件,因此这是一个重大问题。我非常感谢任何人能为我提供的指导。提前感谢!

尽管没有收到任何指导,但这里还有一些额外的r在同事的帮助下,通过一些实验,我终于解决了我的问题

因此,有几个方面很重要。首先,您必须确保要上载的图像通过浏览器(在我的例子中是selenium/node chrome debug)装载到容器中。然后您必须对测试selenium测试文件进行一些添加

必须添加以下行:

var path = require('path');
var remote = require('selenium-webdriver/remote');
您可以使用var或let,尽管我被告知let是一种更好的标准做法

然后,在排队之后

driver = new Builder().forBrowser('chrome').usingServer('http://selenium_hub:4444/wd/hub').build();
添加这行代码

driver.setFileDetector(new remote.FileDetector());
对于要上载的文件,必须将路径设置为浏览器容器上的文件系统路径(在我的示例中为selenium/node chrome debug)。因此,文件变量类似于:

const companyImage = process.cwd()+'/images/backgroundmario.jpg';
然后,当您想要上传文件时,您可以使用您喜欢的任何形式的标识找到相应的元素,并向sendKeys函数添加一点额外的内容,与您在本地文件系统而不是docker容器上运行脚本的方式相比。因此,代码如下所示:

        const companyImage = process.cwd()+ '/img/backgroundmario.jpg';
        const companyImageElem = await driver.findElement(By.xpath("//div/input[@type='file']"));
        await companyImageElem.sendKeys(companyImage);
await driver.findElement(By.xpath("//input[@type='file']")).sendKeys(path.resolve(__dirname, companyImage));
也许有一种更简洁的编码方式(例如,我通常将与之交互的元素声明为变量),但我提供的示例将起作用。我花了很多时间和精力来找到这个解决方案,因此我希望这最终能为其他人省去我在尝试实现这一点时所经历的痛苦