0

我一直在尝试在 Docker 中运行一些量角器测试,但我发现了一个我自己无法解决的问题。Protractor 表示该元素在 Docker 的网页中不存在,但在 localhost 中存在。此外,网页的 CURL 暴露了 HTML 元素(如您所知,不是 Angular 组件中的 HTML),但仍然找不到该元素。

首先,测试在本地主机上正常工作:

/*********** TESTING **********/
beforeAll(function(){
    browser.sleep(1).then(function() {
        console.log('Browser running ...');
    });

    browser.driver.manage().window().getSize().then(function(size) {
        console.log('Starting browser size', size);
    });

    browser.get(specifiedURL+"/app/users/#/register");

    browser.waitForAngular(); //We expect to wait for angular to be loaded so browser can load correctly his components        

    browser.getCurrentUrl().then(function(url){
        console.info("Browser redirected to "+url);
    });

    browser.refresh();  //Refresh the view so it loads the content properly at the specified ngStorage-project url
});

和两个测试

it("should redirect to the specified page", function(){
    expect(browser.getCurrentUrl()).toEqual(specifiedURL+"/app/users/#/register");
});

it("should exists a surname input in the page",function(){
    var displaySurnameInput = element(by.id('signup-surname'));

    browser.wait(function() {
         return displaySurnameInput.isPresent();
    }, 5000);

    expect(displaySurnameInput.getText()).toEqual('');
});

配置文件如

    let SpecReporter = require('jasmine-spec-reporter').SpecReporter;

exports.config = {
  framework: "jasmine2",
  suites: {
    login: "tests/e2e/login/**/*Spec.js"
  },
  multiCapabilities: [{
    browserName: "chrome",
    chromeOptions: {
      args: [ "--headless", "--window-size=1200x800", "--disable-gpu", "--test-type", "--no-sandbox"]
    }
  }],
  jasmineNodeOpts: {
    showColors: true,
    silent: true,
    defaultTimeoutInterval: 360000,
    print: function () { }
  },
  onPrepare: function () {
    jasmine.getEnv().addReporter(new SpecReporter({
      spec: {
        displayStacktrace: false
      }
    }));
  }
}

Docker 链接到暴露于端口 80 的 docker-nginx 服务器,因此我们可以检查项目是否正确运行(确实如此)。当我运行 docker 命令时:

docker run -it -v /dev/shm:/dev/shm --privileged -e SCREEN_WIDTH=1920 -e SCREEN_HEIGHT=1480 -e SCREEN_DEPTH=24 --link ify-nginx:ify-nginx ify/test-runner bash

我可以使用 CURL 访问网页,它会在浏览器中显示网页 HTML(实际上与本地主机中的 curl 返回的结果相同)但不知何故量角器在 URL 中找不到元素(我已经尝试获取多个茉莉花功能的元素,仍然会发生同样的问题)。

本地主机PROTRACTOR_RESULT

DOCKER PROTRACTOR_RESULT

谢谢!

编辑1:

在 docker 中使用它会产生错误,但不会在 localhost

it("should exists a surname input in the page",function(){
    var displaySurnameInput = element(by.id('signup-surname'));

    browser.pause();

    browser.wait(function() {
        return displaySurnameInput.isPresent();
    }, 5000);

    expect(displaySurnameInput.getText()).toEqual('');
});

错误(因为我是新手,我不能粘贴超过 2 张图片,所以我在这里粘贴代码)

[08:33:33] I/protractor -
module.js:487
    throw err;
    ^
Error: Cannot find module '_debugger'

编辑2:

使用

browser.executeScript("return arguments[0].innerHTML;", $('html')).then(function (content) { console.log(content); }); 

我已经打印了显示组件的 html...但不是内部 html(它放置了正确的 id 和实际的输入元素)

    <section ng-show="step==1" style="overflow:hidden;">
            <ify-input id="signup" field="name" ng-model="user.name" class="ng-pristine ng-untouched ng-valid ng-scope"><!-- ngIf: isAllowed(field) --></ify-input>
            <a id="signup-step1" class="ify-button ng-binding" ng-click="step2()">{{ ("Next" | translate).toUpperCase() }}</a>
    </section>

我可以运行一个通过.model 搜索元素的测试,但它不是指内部输入,因为它应该使用 by.id。

it("should find a model.name in the dom", function(){
        var displayNameInput = element(by.model("user.name"));

        browser.wait(function() {
            return displayNameInput.isPresent();
        }, 5000);

        expect(displayNameInput.getText()).toEqual('');
});

问题仍然很清楚,无法获取角度组件的内部 html

编辑3:

我已经测试了这个页面https://docs.angularjs.org/examples/example-heroComponentSimple/index.html并暴露了 HTML,它似乎可以读取组件的内部 html。

暴露的 HTML:

 <body ng-app="heroApp" class="ng-scope">
  <!-- components match only elements -->
<div ng-controller="MainCtrl as ctrl" class="ng-scope">
  <b>Hero</b><br>
  <hero-detail hero="ctrl.hero" class="ng-isolate-scope"><span class="ng-binding">Name: Spawn</span></hero-detail>
</div>

考试:

        it("example component web random",function(){
        browser.get("https://docs.angularjs.org/examples/example-heroComponentSimple/index.html");

        browser.waitForAngular();

browser.executeScript("return arguments[0].innerHTML;", $('html')).then(function (content) { console.log(content); });

        expect(element(by.css('.ng-binding')).isPresent()).toBe(true);
    });
4

3 回答 3

0

Protractor 表示该元素在 Docker 的网页中不存在,但在 localhost 中存在。此外,网页的 CURL 暴露了 HTML 元素(如您所知,不是 Angular 组件中的 HTML),但仍然找不到该元素。

有点误导,或者可能是因为我的英语不好。我也有一个类似的错误。所以我试着解释我是如何解决我的问题的。

  1. 进行头脑风暴:可能是什么原因?有时它会超过 1。请确保您逐步找出什么不工作以及什么是 100% 工作。您尝试使用 browser.wait 调试量角器应用程序,这是正确的方向,但它在 Node.js 8+ 中不起作用,您可能想尝试量角器快照
  2. 写下这些原因,对我来说有:https(我有一个自分配的证书可以在访问https://localhost:8443之类的站点时手动验证),localhost可以在 dev 上工作,例如在 mac 上,但可能不会在 docker 容器中工作,因为每个容器都有不同的 ip(我更喜欢 docker-compose,因为它更干净?),您可以将静态 ip 分配给 docker 容器(我也不知道)
  3. 从 http 和 localhost 开始 capabilities: { browserName: 'chrome', chromeOptions: { // for ci test args: ['--headless', 'no-sandbox', "--disable-browser-side-navigation", "--allow-insecure-localhost" /// for https sites: ignore ssl on https://localhost... /// further args please see https://peter.sh/experiments/chromium-command-line-switches/ ] // maybe you want to take some screenshots to test where the error occurs: } }
  4. 使用一些 docker 命令进行调试,这里快照量角器派上用场: docker inspect --format "{{json .State.Health }}" [container_name] | jq docker cp [container_id]:/xxx/xxx/xxxLocalhost.png . docker exec -it bewertungsapp_webapp_1 bash # or sh for alpine node 对我来说,第二个对我帮助最大(将快照从 docker 复制到我的开发/主机),因为我看到的是一个空白页
  5. docker-compose.yml:为 3 个图像分配静态 ip

    version: "3" 
    # docker-compose version: 1.21.1 for version 3 
    
    services:
      server:
        build: server
        ports:
          - "4000:4000"
          - "8443:8443"
        links:
          - mongo
        depends_on:
          - mongo
        networks:
          app_net:
            ipv4_address: 192.17.1.3 # other address will also do, but on my dev 172.17.x.x is reserved for docker e.g.
        healthcheck:
          # test: ["CMD", "curl", "-k", "https://localhost:8443"]
          # test: ifconfig
          test: curl -k http://192.17.1.3:8443 # you may want to install curl first
          # test: curl http://localhost:8443/bundle.js -k -s | grep -C 3 "window.pushNotification"
          interval: 30s
          timeout: 10s
          retries: 3
    
      mongo:
        image: mongo
        ports:
          - "27017:27017"
        networks:
          app_net:
          # static different ip for mongo
            ipv4_address: 192.17.1.2
    
      # this is actually only protractor build for me        
      webapp:
        build: webapp
        restart: on-failure
        depends_on:
          - server
        links:
          - server
          networks:
          app_net:
            # another static different ip for webapp
              ipv4_address: 192.17.1.4
    
      networks:
        app_net:
          driver: bridge
          driver_opts:
            com.docker.network.enable_ipv6: "false"
          ipam:
            driver: default
            config:
            - subnet: 192.17.1.0/24
    
  6. 屏幕截图/快照的量角器脚本

    import fs from 'fs';
    import path from "path";
    
    function writeScreenShot(data, filename) {
        console.info("writeScreenShot filename: ", filename);
        const stream = fs.createWriteStream(filename);
        stream.write(new Buffer(data, 'base64'));
        stream.end();
    }
    
    export function takeScreenshot(browser, timeStamp){
        const pathForScreenshot = path.resolve(__dirname, '../screenshots');
        console.info("takeScreenshot pathForScreenshot: ", pathForScreenshot);
        if (!fs.existsSync(pathForScreenshot)) {
            fs.mkdirSync(pathForScreenshot);
        }
    
        browser.takeScreenshot().then((png) => {
            writeScreenShot(png, path.resolve(pathForScreenshot, timeStamp));
        });
    }
    
    export const baseUrl = 'http://192.17.1.3:8443'; /// docker
    
  7. --allow-insecure-localhost 实际上对于 localhost 来说已经足够了,但是对于任意地址 ssl 我仍在寻找它... :) 祝愿

于 2018-06-07T19:45:31.620 回答
0

Docker 试图在http://ify-nginx/api/连接一个不存在的 API ...该调用期望在注册表单上生成一个必填字段列表。返回 null 时,不会生成字段,本身,量角器什么也找不到。

正如您在上面看到的,这里发生了一些奇怪的事情(ngIf:isAllowed)

<ify-input id="signup" field="name" ng-model="user.name" class="ng-pristine ng-untouched ng-valid ng-scope"><!-- ngIf: isAllowed(field) --></ify-input>

我们在 api 代码中有一个 if 检查 url 是 'localhost' 还是服务器 ip,而不是 'ify-nginx'。当检测到 ify-nginx 时,将 api 域重定向到它,并且它不加载内容。

于 2017-06-27T06:20:22.067 回答
0

你错过了一个“;” 在 browser.wait 内返回的最后。另外,尝试

return displaySurnameInput.isPresent();

5 秒足以加载页面吗?

您还可以通过禁用报告库来禁用获取有关问题的更多详细信息。或者它可以选择显示更多细节。

如果你使用 browser.ignoreSynchronisation = true; 在 browser.wait 之前和等待之后的 false ,它会改变什么吗?

于 2017-06-21T15:27:33.780 回答