How to run browser based cucumber tests using grunt in docker container

I have a set of unit tests which needs to be executed after each build. For this scenario, after each build I am creating a docker container and for running cucumber tests.

Those test cases needs chrome for execution. I have installed chrome on docker but when unit tests are initiated they timeout as unit test cases are not able to access the browser.

Below is the grunt code for running unit tests in browser:

'use strict';

const path = require('path');

module.exports = (grunt) => {

    grunt.initConfig({

        // Configuration to be run (and then tested).
        chrome_headless: {
            options: {
                args: ['--disable-gpu']
            },
            default_options: {
            },
            custom_options: {
                options: {
                    port: 9999
                }
            }
        },
        env: {
            chrome: {
                PLATFORM: 'ChromeCanary',
                base: 'ChromeCanary',
                flags: [
                    '--no-sandbox',
                    // See https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
                    '--headless',
                    '--disable-gpu',
                    // Without a remote debugging port, Google Chrome exits immediately.
                    ' --remote-debugging-port=9222',
                ]
            },
            firefox: {
                PLATFORM: 'FIREFOX'
            }
        },

        jshint: {
            all: ['Gruntfile.js', 'features/step_definitions/*.js', 'features/support/*.js'],
            options: {
                node: true,
                strict: "global",
                esversion: 6
            }
        },

        exec: {
            run_cucumber_tests: {
                command: path.join('node_modules', 'cucumber',  'bin', 'cucumber.js')
            }
        }

    });
    grunt.registerTask('grunt-chrome_headless');
    //grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-exec');
    grunt.loadNpmTasks('grunt-env');

    grunt.registerTask('default', ['env:chrome', 'exec']);
    //grunt.registerTask('chrome', ['env:chrome', 'jshint', 'exec']);
    //grunt.registerTask('firefox', ['env:firefox', 'jshint', 'exec']);

};

Can anyone please suggest me how this can be achieved...

  • Error: function timed out, ensure the callback is executed within 5000 milliseconds

    I'm using Protractor 5.1.2, npm 5.6.0 It's failing when It tries to click on Login button. I'm getting "Error: function timed out, ensure the callback is executed within 5000 milliseconds" I cannot find where can I change these 5000 milliseconds

    homepage.step.ts

    import { AppPage } from '../../pageobjects/app';
    import { Homepage } from '../../pageobjects/homepage';
    import { browser, element, by } from 'protractor';
    const { Before } = require('cucumber');
    const { Given } = require("cucumber");
    const { When } = require("cucumber");
    const { Then } = require("cucumber");
    const { setDefaultTimeout } = require ("cucumber");
    const chai = require("chai").use(require("chai-as-promised"));
    const expect = chai.expect;
    let page: AppPage;
    let homepage: Homepage;
    
    Before(() => {
    page = new AppPage();
    homepage = new Homepage();
    });
    
    Given('I am on the login page', function () {
          page.navigateTo();
    });
    
    When('I fill in teller with {string}', function (string) {
    
    homepage.teller.sendKeys(string);
    
    });
    
    When('I fill in pin with {string}', function (string) {
    
    homepage.pin.sendKeys(string);
    
    });
    
    When('I press Login', function (string) {
    
    homepage.loginButton.click();
    
    });
    
    Then('I should see the {string}', function (string) {
    
    expect(homepage.sideBar).to.eventually.equal(string);
    
    });
    

    protractor.conf.js

    exports.config = {
    allScriptsTimeout: 11000,
    
    specs: [
        './e2e/features/*.feature'
    ],
    
    capabilities: {
        browserName: 'chrome'
    },
    directConnect: true,
    baseUrl: 'http://localhost:4200/',
    framework: 'custom',
    frameworkPath: require.resolve('protractor-cucumber-framework'),
    cucumberOpts: {
        require: 'e2e/features/step_definitions/*.step.ts',
        tags: [], // <string[]> (expression) only execute the features or scenarios with tags matching the expression
        strict: true, // <boolean> fail if there are any undefined or pending steps
        //format: ["pretty"],            // <string[]> (type[:path]) specify the output format, optionally supply PATH to redirect formatter output (repeatable)
        'dry-run': false, // <boolean> invoke formatters without executing steps
        compiler: [] // <string[]> ("extension:module") require files with the given EXTENSION after requiring MODULE (repeatable)
    },
    
    onPrepare() {
        require('ts-node').register({
            project: 'e2e/tsconfig.e2e.json',
        });
    },
    

    };

    PO

    import { by,ProtractorBy, element } from "protractor";
    export class Homepage {
    
    sideMenu = element(by.css('.sidebar-nav'));
    statusBar = element(by.css('.status-bar-content'));
    container = element(by.css('.container-fluid'));
    teller = element (by.css('[formcontrolname=user_id]'));
    pin= element (by.css('[formcontrolname=pin]'));
    loginButton = element(by.buttonText('Login'));
    sideBar= element(by.className('.sidebar'));
    activeNav = element (by.css('.nav-link active'));
    }
    

    I'm getting the following error:

    Failures:
    
    1) Scenario: login with valid credentials # e2e\features\login.feature:12
    √ Before # e2e\features\step_definitions\homepage.step.ts:15
    √ Before # e2e\features\step_definitions\login.step.ts:15
    √ Given I am on the login page # 
    e2e\features\step_definitions\login.step.ts:35
    √ When I fill in teller with "1" # 
    e2e\features\step_definitions\login.step.ts:41
    √ When I fill in pin with "1" # 
    e2e\features\step_definitions\login.step.ts:47
    × When I press Login # e2e\features\step_definitions\login.step.ts:53
       Error: function timed out, ensure the callback is executed within 5000 
       milliseconds
       at Timeout._onTimeout (C:\ui- 
       terminal\node_modules\cucumber\src\user_code_runner.js:61:18)
       at ontimeout (timers.js:482:11)
       at tryOnTimeout (timers.js:317:5)
       at Timer.listOnTimeout (timers.js:277:5)
    - When I should see the "sidebar" # 
    e2e\features\step_definitions\login.step.ts:61
    - Then I should see the home menue option active # 
    e2e\features\step_definitions\login.step.ts:74
    
  • Karate - Display title of called features / scenarios in cucumber reports

    I have a very huge scenario, where I have automated an end to end test with a lot of requests to different API. Every service call of an API is in an extra feature file and called in the main scenario.

    The problem is, that the generated cucumber report is getting really unclear and I would love to make them a little bit more readable by displaying the title of the called feature files and also the scenario title preferebly. Is this somehow possible?

    So instead of just printing:

    call classpath:feature/rm/msisdn/rm-msisdn-reservation-add.feature
    

    It would be nice to have this:

    Reserve MSISDN  
    call classpath:feature/rm/msisdn/rm-msisdn-reservation-add.feature
    

    Any help would be very much appreciated!

    cheerio

  • Mocha with Vue: Resolution method is overspecified

    this is my test:

    describe('Documentation Component', () => {
      it('renders a vue instance', (done) => {
        expect(shallow(Documentation).isVueInstance()).toBe(true)
        done()
      })
    
      it('Gets documentation', async (done) => {
        let wrapper = shallow(Documentation)
    
        await flushPromises()
        expect(wrapper.vm.$data.documentation).toBe('')
        done()
      })
    })
    

    I followed the guide in the Vue.js docs and I can't get this to work. I need to wait for the docs promise:

    mounted () {
        // --------------------------------------
        this.$http.get(Config.urls.documentation).then(
          (response) => {
            this.documentation = response.body
          },
          (errorResponse) => {
            EventBridge.$emit('request.error', errorResponse)
            this.documentation = ''
          }
        )
      }
    

    The thing is, if I use the "done" function gives this error and without it, it gives this:

    Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called;
    

    I'm not sure what I need to do, just followed the docs. :(

  • how to change span display style,when the span not has ID

    enter image description here

    my automation case ,when Mouse movement a favorite button display like this*, i click this icon,this game will add to favorite, could anybody help me,thanks

    it('Mouse movement, favorite button display, click to join',function(){
    
        var text=$('//*[@id="SSC"]/div/span[3]')
        var attr1 = text.getAttribute('display')
        console.log("---------------"+attr1)
        //text.scroll()
        //browser.actions()
        var js = 'document.getElementsByTagName("span")[3].style.display="block"'
        browser.execute(js)
        var attr2 = text.getAttribute('display')
        console.log("---------------"+attr2)
        browser.click('//*[@id="SSC"]/div/span[3]');
    
    })  
    
  • Unit Testing React-Redux Connected Components in Enzyme

    I have a connected component with Form and button. While unit testing the component using mount , i get the error "Actions must be plain objects."

    handleSubmit({ values }) {
        const {url} = this.props;
        const val = values.valcode;
        this.props.actions.getCode(url);
        this.props.makeExternalCall(val);
      }
    
    
      return (
              <Form
                initialValues={{ ...personalUser }}
                onSubmit={this.handleSubmit}>
                {
                  ({ form, errors }) => {
                    const isDisabled = errors !== null || this.state.disableReset;
    
                    return (
                      <div>
                        <button name="btnConfirm" type="submit"
                          className={styles.btnConfirm} disabled={isDisabled}>/>
                        </button>
                      </div>
                    );
                  }
                }
              </Form>
            );
    
    const mapDispatchToProps = (dispatch) => ({
      actions: bindActionCreators(actions, dispatch),
      makeExternalCall: bindActionCreators(makeExternalCallAction, dispatch)
    });
    
    export default connect(null, mapDispatchToProps)(injectIntl(TestComponent));
    

    Test

    it(" - should display the proper label", () => {
    
        props.error = "This is an error message";
        props.actions.getCode = sinon.stub().returns({
          then: () => {}
        });
        props.makeExternalCall = sinon.stub().returns({
          then: () => {}
        });
        store = mockStore(props);
        const wrapper = mountWithIntl(<Provider store={store}>
            <TestComponent {...props}/>
          </Provider>);
        expect(wrapper).to.not.be.null;
        expect(wrapper.find("button").prop("disabled")).equals(true);
       wrapper.find("TestComponent").get(0).handleSubmit({values:{valcode: "AkPdQ2" }});
      });
    

    Is it possible to mock the mapDispatchToProps ,which is giving the error

    PhantomJS 2.1.1 (Mac OS X 0.0.0) <TestComponent Component />  - should display the proper label FAILED
        Actions must be plain objects. Use custom middleware for async actions.