angular / protractor

E2E test framework for Angular apps
http://www.protractortest.org
MIT License
8.75k stars 2.31k forks source link

Running protractor with jenkins in headless machine problems. #2498

Closed lganet closed 9 years ago

lganet commented 9 years ago

Hi, I'm executing a jenkins jobs in my cloud machine, it is a headless machine. OS: Linux 3.13.0-32-generic #57-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux protractor: Version 2.2.0 selenium-server-standalone-2.45.0.jar I'm using xvfb to emulate the display. node: v0.12.7 java: 1.8.0_60 In my development machine it works fine and fast, but in headless machine is not working, in all tests are returning a jasmine timed out as answer.

Below I put: Selenium stdou, Jenkins stdou, protractor conf and my test.

Stdout of selenium:

16:55:10.513 INFO - Launching a standalone server
Setting system property webdriver.chrome.driver to chromedriver
16:55:10.621 INFO - Java: Oracle Corporation 25.60-b23
16:55:10.621 INFO - OS: Linux 3.13.0-32-generic amd64
16:55:10.647 INFO - v2.45.0, with Core v2.45.0. Built from revision 5017cb8
16:55:10.843 INFO - Default driver org.openqa.selenium.ie.InternetExplorerDriver registration is skipped: registration capabilities Capabilities [{ensureCleanSession=true, browserName=internet explorer, version=, platform=WINDOWS}] does not match with current platform: LINUX
16:55:10.934 INFO - RemoteWebDriver instances should connect to: http://127.0.0.1:4444/wd/hub
16:55:10.936 INFO - Version Jetty/5.1.x
16:55:10.940 INFO - Started HttpContext[/selenium-server,/selenium-server]
16:55:10.997 INFO - Started org.openqa.jetty.jetty.servlet.ServletHandler@2a18f23c
16:55:10.998 INFO - Started HttpContext[/wd,/wd]
16:55:10.998 INFO - Started HttpContext[/selenium-server/driver,/selenium-server/driver]
16:55:10.998 INFO - Started HttpContext[/,/]
16:55:11.008 INFO - Started SocketListener on 0.0.0.0:4444
16:55:11.008 INFO - Started org.openqa.jetty.jetty.Server@b1bc7ed
16:55:33.865 INFO - Executing: [new session: Capabilities [{proxy={httpProxy=http://proxy.nuvemluiza.intranet:8080, proxyType=manual, noProxy=.nuvemluiza.intranet,.cloudml.intranet,.magazineluiza.intranet,localhost,127.0.0.1}, count=1, browserName=chrome}]])
16:55:33.886 INFO - Creating a new session for Capabilities [{proxy={httpProxy=http://proxy.nuvemluiza.intranet:8080, proxyType=manual, noProxy=.nuvemluiza.intranet,.cloudml.intranet,.magazineluiza.intranet,localhost,127.0.0.1}, count=1, browserName=chrome}]
Starting ChromeDriver 2.15.322448 (52179c1b310fec1797c81ea9a20326839860b7d3) on port 23373
Only local connections are allowed.
16:55:36.513 INFO - Done: [new session: Capabilities [{proxy={httpProxy=http://proxy.nuvemluiza.intranet:8080, proxyType=manual, noProxy=.nuvemluiza.intranet,.cloudml.intranet,.magazineluiza.intranet,localhost,127.0.0.1}, count=1, browserName=chrome}]]
16:55:36.578 INFO - Executing: [set script timeoutt: 11000])
16:55:36.590 INFO - Done: [set script timeoutt: 11000]
16:55:36.778 INFO - Executing: [maximise window])
16:55:36.963 INFO - Done: [maximise window]
16:55:36.981 INFO - Executing: [get: data:text/html,<html></html>])
16:55:37.011 INFO - Done: [get: data:text/html,<html></html>]
16:55:37.023 INFO - Executing: [execute script: window.name = "NG_DEFER_BOOTSTRAP!" + window.name;window.location.replace("http://localhost:8080/");, []])
16:56:36.826 INFO - Executing: [execute async script: try { return (function (rootSelector, callback) {
  var el = document.querySelector(rootSelector);

  try {
    if (!window.angular) {
      throw new Error('angular could not be found on the window');
    }
    if (angular.getTestability) {
      angular.getTestability(el).whenStable(callback);
    } else {
      if (!angular.element(el).injector()) {
        throw new Error('root element (' + rootSelector + ') has no injector.' +
           ' this may mean it is not inside ng-app.');
      }
      angular.element(el).injector().get('$browser').
          notifyWhenNoOutstandingRequests(callback);
    }
  } catch (err) {
    callback(err.message);
  }
}).apply(this, arguments); }
catch(e) { throw (e instanceof Error) ? e : new Error(e); }, [body]])
16:57:36.854 INFO - Executing: [execute async script: try { return (function (rootSelector, callback) {
  var el = document.querySelector(rootSelector);

  try {
    if (!window.angular) {
      throw new Error('angular could not be found on the window');
    }
    if (angular.getTestability) {
      angular.getTestability(el).whenStable(callback);
    } else {
      if (!angular.element(el).injector()) {
        throw new Error('root element (' + rootSelector + ') has no injector.' +
           ' this may mean it is not inside ng-app.');
      }
      angular.element(el).injector().get('$browser').
          notifyWhenNoOutstandingRequests(callback);
    }
  } catch (err) {
    callback(err.message);
  }
}).apply(this, arguments); }
catch(e) { throw (e instanceof Error) ? e : new Error(e); }, [body]])
16:57:44.562 INFO - Done: [execute script: window.name = "NG_DEFER_BOOTSTRAP!" + window.name;window.location.replace("http://localhost:8080/");, []]
16:57:44.619 INFO - Done: [execute async script: try { return (function (rootSelector, callback) {
  var el = document.querySelector(rootSelector);

  try {
    if (!window.angular) {
      throw new Error('angular could not be found on the window');
    }
    if (angular.getTestability) {
      angular.getTestability(el).whenStable(callback);
    } else {
      if (!angular.element(el).injector()) {
        throw new Error('root element (' + rootSelector + ') has no injector.' +
           ' this may mean it is not inside ng-app.');
      }
      angular.element(el).injector().get('$browser').
          notifyWhenNoOutstandingRequests(callback);
    }
  } catch (err) {
    callback(err.message);
  }
}).apply(this, arguments); }
catch(e) { throw (e instanceof Error) ? e : new Error(e); }, [body]]
16:57:44.641 INFO - Done: [execute async script: try { return (function (rootSelector, callback) {
  var el = document.querySelector(rootSelector);

  try {
    if (!window.angular) {
      throw new Error('angular could not be found on the window');
    }
    if (angular.getTestability) {
      angular.getTestability(el).whenStable(callback);
    } else {
      if (!angular.element(el).injector()) {
        throw new Error('root element (' + rootSelector + ') has no injector.' +
           ' this may mean it is not inside ng-app.');
      }
      angular.element(el).injector().get('$browser').
          notifyWhenNoOutstandingRequests(callback);
    }
  } catch (err) {
    callback(err.message);
  }
}).apply(this, arguments); }
catch(e) { throw (e instanceof Error) ? e : new Error(e); }, [body]]
16:59:48.031 INFO - Executing: [find elements: By.cssSelector: .btn.btn-default])
16:59:48.046 INFO - Done: [find elements: By.cssSelector: .btn.btn-default]
16:59:48.061 INFO - Executing: [is enabled: 1 [[ChromeDriver: chrome on LINUX (b19a86fa168764a993662564c2b0d13d)] -> css selector: .btn.btn-default]])
16:59:48.070 INFO - Done: [is enabled: 1 [[ChromeDriver: chrome on LINUX (b19a86fa168764a993662564c2b0d13d)] -> css selector: .btn.btn-default]]
17:00:18.149 INFO - Executing: [delete session: 55770e65-0511-4df4-8dc1-56562b7c0a10])
17:00:18.721 INFO - Done: [delete session: 55770e65-0511-4df4-8dc1-56562b7c0a10]

Log of jenkins:

+ echo Rodando os testes do protractor
Rodando os testes do protractor
+ echo :99
:99
+ node --version
v0.12.7
+ protractor conf.js
Using the selenium server at http://localhost:4444/wd/hub
[launcher] Running 1 instances of WebDriver
Started
A Jasmine spec timed out. Resetting the WebDriver Control Flow.
FA Jasmine spec timed out. Resetting the WebDriver Control Flow.
A Jasmine spec timed out. Resetting the WebDriver Control Flow.
FA Jasmine spec timed out. Resetting the WebDriver Control Flow.
FA Jasmine spec timed out. Resetting the WebDriver Control Flow.
FA Jasmine spec timed out. Resetting the WebDriver Control Flow.
FA Jasmine spec timed out. Resetting the WebDriver Control Flow.
FA Jasmine spec timed out. Resetting the WebDriver Control Flow.
FA Jasmine spec timed out. Resetting the WebDriver Control Flow.
F

Failures:
1) Testando Login UC 1 - O botão de login deve estar desabilitado, pois apenas acessei a tela.
  Message:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Stack:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

2) Testando Login UC 2 - O botão de login deve estar desabilitado, pois preenchi apenas o login
  Message:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Stack:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Message:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Stack:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

3) Testando Login UC 3 - O botão de login deve estar desabilitado, pois preenchi apenas a senha
  Message:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Stack:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Message:
    Failed: Error while waiting for Protractor to sync with the page: "[ng:test] http://errors.angularjs.org/1.4.5/ng/test"
  Stack:
    Error: Failed: Error while waiting for Protractor to sync with the page: "[ng:test] http://errors.angularjs.org/1.4.5/ng/test"

4) Testando Login UC 4 - O botão de login deve estar habilitado, pois preenchi os dois campos
  Message:
    Failed: Error while waiting for Protractor to sync with the page: "[ng:test] http://errors.angularjs.org/1.4.5/ng/test"
  Stack:
    Error: Failed: Error while waiting for Protractor to sync with the page: "[ng:test] http://errors.angularjs.org/1.4.5/ng/test"
  Message:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Stack:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Message:
    Failed: undefined is not a function
  Stack:
    TypeError: undefined is not a function
        at Object.<anonymous> (/var/lib/jenkins/jobs/UCWEB/workspace/testes/loginTeste.js:58:40)
    From: Task: Run it("4 - O botão de login deve estar habilitado, pois preenchi os dois campos") in control flow
    From asynchronous test: 
    Error
        at Suite.<anonymous> (/var/lib/jenkins/jobs/UCWEB/workspace/testes/loginTeste.js:53:5)
        at Object.<anonymous> (/var/lib/jenkins/jobs/UCWEB/workspace/testes/loginTeste.js:5:1)

5) Testando Login UC 5 - Mensagem de erro deve ser exibida, com usuário inválido.
  Message:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Stack:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Message:
    Failed: undefined is not a function
  Stack:
    TypeError: undefined is not a function
        at Object.<anonymous> (/var/lib/jenkins/jobs/UCWEB/workspace/testes/loginTeste.js:67:40)
    From: Task: Run it("5 - Mensagem de erro deve ser exibida, com usuário inválido.") in control flow
    From asynchronous test: 
    Error
        at Suite.<anonymous> (/var/lib/jenkins/jobs/UCWEB/workspace/testes/loginTeste.js:62:5)
        at Object.<anonymous> (/var/lib/jenkins/jobs/UCWEB/workspace/testes/loginTeste.js:5:1)

6) Testando Login UC 6 - Mensagem de erro deve ser exibida, com senha inválido.
  Message:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Stack:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Message:
    Failed: undefined is not a function
  Stack:
    TypeError: undefined is not a function
        at Object.<anonymous> (/var/lib/jenkins/jobs/UCWEB/workspace/testes/loginTeste.js:105:40)
    From: Task: Run it("6 - Mensagem de erro deve ser exibida, com senha inválido.") in control flow
    From asynchronous test: 
    Error
        at Suite.<anonymous> (/var/lib/jenkins/jobs/UCWEB/workspace/testes/loginTeste.js:100:5)
        at Object.<anonymous> (/var/lib/jenkins/jobs/UCWEB/workspace/testes/loginTeste.js:5:1)

7) Testando Login UC 8 - Login feito com sucesso, utilizado Login: lganet Senha: 12345
  Message:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Stack:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Message:
    Failed: undefined is not a function
  Stack:
    TypeError: undefined is not a function
        at Object.<anonymous> (/var/lib/jenkins/jobs/UCWEB/workspace/testes/loginTeste.js:169:40)
    From: Task: Run it("8 - Login feito com sucesso, utilizado Login: lganet Senha: 12345") in control flow
    From asynchronous test: 
    Error
        at Suite.<anonymous> (/var/lib/jenkins/jobs/UCWEB/workspace/testes/loginTeste.js:164:86)
        at Object.<anonymous> (/var/lib/jenkins/jobs/UCWEB/workspace/testes/loginTeste.js:5:1)

8) Testando Login UC 9999 - Para fechar.
  Message:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Stack:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

8 specs, 8 failures
Finished in 281.413 seconds
[launcher] 0 instance(s) of WebDriver still running
[launcher] chrome #1 failed 8 test(s)
[launcher] overall: 8 failed spec(s)
[launcher] Process exited with error code 1
Build step 'Execute shell' marked build as failure
Finished: FAILURE

Source of my conf.js

var Jasmine2HtmlReporter = require('protractor-jasmine2-html-reporter');

exports.config = {
  // Specify you want to use jasmine 2.x as you would with mocha and cucumber.
  seleniumAddress: 'http://localhost:4444/wd/hub',
  seleniumPort: 4444,
  //specs: ['testes/loginTeste.js'],

 suites: {
    login: 'testes/loginTeste.js',
    //configuracao: 'testes/configuracaoTeste.js'
  },
  mocks: {
    dir: 'testes/mocks',
    default: ['autenticacao']
  },
  framework: 'jasmine2',
  capabilities: {
    'browserName': 'chrome',
    'proxy': {
         'proxyType': 'manual',
         'httpProxy': 'http://proxy.nuvemluiza.intranet:8080',
         'noProxy': '.nuvemluiza.intranet,.cloudml.intranet,.magazineluiza.intranet,localhost,127.0.0.1',
      }
    }, 
    // multiCapabilities: [
    //  {'browserName': 'firefox'}, 
    //  {'browserName': 'chrome'}
    // ],
   // Options to be passed to Jasmine-node.
  jasmineNodeOpts: {
    showColors: false, // Use colors in the command line report.
    //defaultTimeoutInterval: 100000,
  },
  //directConnect: true,
  onPrepare: function() {
        require('protractor-http-mock').config = {
            rootDirectory: __dirname, // default value: process.cwd()
            protractorConfig: 'conf.js' // default value: 'protractor.conf'
        };

        jasmine.getEnv().addReporter(
            new Jasmine2HtmlReporter(
                {
                    savePath: __dirname + '/web/testes/',
                    takeScreenshots: true,
                    screenshotsFolder: 'imagens',
                    filePrefix: 'report',
                }));

                beforeEach(function() {
                    jasmine.addMatchers({
                        toBeCustom: function(util, customEqualityTesters) {
                            return {
                                compare: function(actual, expected, message) {
                                    var passed = actual == expected

                                     return {
                                        pass: passed,
                                        message: message + '<br>É esperado "' + expected + '"' + ' e o valor é igual á "' + actual + '".'
                                    };
                                }
                            };
                        }
                    });
                });
    },
};

my test file

var util = require('../testes/utils'),
    mock = require('protractor-http-mock');

describe('Testando Login UC', function() {

    afterEach(function(){
        mock.teardown();
    });

    var botaoLogar =  $('.btn.btn-default'); // element(by.css('.btn.btn-default'));
    var campoLogin = element(by.model('usuario.login'));
    var campoSenha = element(by.model('usuario.senha'));
    var botaoOkMensagem = $('button.confirm');
    var usuarioValido = 'lganet';
    var usuarioInvalido = 'usuarioInvalido';
    var senhaValida = '12345';
    var senhaInvalida = 'senhaInvalida';
    var mensagemEsperadaPassWord = "Password inválido.";
    var mensagemEsperadaUsuario = "Funcionário não encontrado.";
    var mensagemFalhaAcessoAPI = "Problemas ao consultar o serviço de autenticação.";

    it('1 - O botão de login deve estar desabilitado, pois apenas acessei a tela.', function() {

        mock(['autenticacao']);
        browser.driver.manage().window().maximize();
        browser.get('http://localhost:8080');
        //browser.get('http://localhost:8080');
        element(by.css('[ng-click="AcaoUsuario()"]')).click();
        expect(botaoLogar.isEnabled()).toBeCustom(false, 'O botão deveria estar desabilitado.');
    });

    it('2 - O botão de login deve estar desabilitado, pois preenchi apenas o login', function() {

        campoLogin.clear().sendKeys(usuarioInvalido);
        campoSenha.clear();

        expect(botaoLogar.isEnabled()).toBeCustom(false, 'O botão deveria estar desabilitado.');

    });

    it('3 - O botão de login deve estar desabilitado, pois preenchi apenas a senha', function() {

        campoLogin.clear();
        campoSenha.clear().sendKeys(senhaInvalida);

        expect(botaoLogar.isEnabled()).toBeCustom(false, 'O botão deveria estar desabilitado.');

    });

    it('4 - O botão de login deve estar habilitado, pois preenchi os dois campos', function() {

        campoLogin.clear().sendKeys(usuarioInvalido);
        campoSenha.clear().sendKeys(senhaInvalida);

        expect(botaoLogar.isEnabled()).toBeCustom(true, 'O botão deveria estar habilitado.');

    });

    it('5 - Mensagem de erro deve ser exibida, com usuário inválido.', function() {

        campoLogin.clear().sendKeys(usuarioInvalido);
        campoSenha.clear().sendKeys(senhaInvalida);

        expect(botaoLogar.isEnabled()).toBeCustom(true, 'O botão deveria estar Habilitado.');

        botaoLogar.click();

        // element(by.css('.sa-icon.sa-error.animateErrorIcon')).getAttribute('style').then(function(attr) {
        //         expect(attr).toMatch(/display\: block;/);
        //     });

        element.all(by.css('.sa-icon.sa-error.animateErrorIcon')).each(function (a) {

            var linkTarget = a.getAttribute('style').then(function(attr) {
                //expect(attr).toMatch(/display\: block;/);
                expect(attr).toBeCustom("display: block;", 'Não foi encotrando a mensagem de erro.');
            });

        });

        element.all(by.css('.showSweetAlert p[style="display: block;"]')).each(function (a) {
            a.getInnerHtml().then(function(text){
                expect(text).toBeCustom(mensagemEsperadaUsuario, 'Não foi encotrando a mensagem de "'+ mensagemEsperadaUsuario +'".');
                botaoOkMensagem.click();
            });
            // var linkTarget = a.getAttribute('style').then(function(attr) {
            //     console.log(attr);
            // });

        });

    });

    it('6 - Mensagem de erro deve ser exibida, com senha inválido.', function() {

        campoLogin.clear().sendKeys(usuarioValido);
        campoSenha.clear().sendKeys(senhaInvalida);

        expect(botaoLogar.isEnabled()).toBeCustom(true, 'O botão deveria estar Habilitado.');

        botaoLogar.click();

        element.all(by.css('.sa-icon.sa-error.animateErrorIcon')).each(function (a) {

            var linkTarget = a.getAttribute('style').then(function(attr) {
                //expect(attr).toMatch(/display\: block;/);
                expect(attr).toBeCustom("display: block;", 'Não foi encotrando a mensagem de erro.');
            });

        });

        element.all(by.css('.showSweetAlert p[style="display: block;"]')).each(function (a) {
            a.getInnerHtml().then(function(text){
                //expect(text).toMatch(/Problemas ao consultar o serviço de autenticação\./);
                expect(text).toBeCustom(mensagemEsperadaPassWord, 'Não foi encotrando a mensagem de "'+ mensagemEsperadaPassWord +'".');
                botaoOkMensagem.click();
            });
            // var linkTarget = a.getAttribute('style').then(function(attr) {
            //     console.log(attr);
            // });

        });

    });

    it('8 - Login feito com sucesso, utilizado Login: ' + usuarioValido + ' Senha: ' + senhaValida, function() {

        campoLogin.clear().sendKeys(usuarioValido);
        campoSenha.clear().sendKeys(senhaValida);

        expect(botaoLogar.isEnabled()).toBeCustom(true, 'O botão deveria estar Habilitado.');

        botaoLogar.click();

        if (element.all(by.css('.sa-icon.sa-error.animateErrorIcon')).count() > 0){

            element.all(by.css('.sa-icon.sa-error.animateErrorIcon')).each(function (a) {   

                var linkTarget = a.getAttribute('style').then(function(attr) {
                    //expect(attr).toMatch(/display\: block;/);
                    expect(attr).toBeCustom("display: block;", 'Não foi encotrando a mensagem de erro.');
                });

            });

            element.all(by.css('.showSweetAlert p[style="display: block;"]')).each(function (a) {
                a.getInnerHtml().then(function(text){
                    //expect(text).toMatch(/Problemas ao consultar o serviço de autenticação\./);
                    expect(text).toBeCustom("Deveria ter logado", 'O sistema não conseguiu logar.');
                    botaoOkMensagem.click();
                });
            }); 
        }else{

            element.all(by.css('.glyphicon-log-out')).count().then(function(total){
                expect(true).toBeCustom(total > 0, 'Não ocorreu o login. Ocorreu uma falha ao fornecer os usuários e senhas corretas.');
            });

        }
    });

    it('9999 - Para fechar.', function() {
        expect(true).toEqual(true);
    });

});
NickTomlin commented 9 years ago

Hi there!

Your question is better suited for StackOverflow. Please ask a question there with the 'protractor' tag to get help.

From the the getting help section of the README:

Please ask usage and debugging questions on StackOverflow (use the "protractor" tag) or in the Angular discussion group. (Please do not ask support questions here on Github.)

It'd also be really helpful to have a more isolated use case. There is a lot of scrolling to do in your current example :smile:

lganet commented 9 years ago

Sorry for the scrolling, I removed some lines of selenium stdout result.

Thank's.