Skip to content

gogoyqj/karma-event-driver-ext

Folders and files

NameName
Last commit message
Last commit date

Latest commit

82d550e · Jun 15, 2017

History

41 Commits
May 23, 2017
May 25, 2017
May 23, 2017
May 3, 2017
May 23, 2017
May 23, 2017
May 23, 2017
May 23, 2017
May 26, 2017
Apr 20, 2017
Jun 15, 2017
Apr 28, 2017
May 26, 2017
Jun 5, 2017
May 26, 2017

Repository files navigation

karma-event-driver-ext

Join the chat at https://gitter.im/karma-event-driver-ext/Lobby

Build Status

Introduction


Logic

This project aims to integrate webdriverio into karma, for writing event-drive-tests conveniently.

for example, in your browser side test code, call webdriverio api to simulate dragAndMove behavior:

        await browser
            .moveToObject(document.body, 0, 0) // top-left corner
            .buttonDown() // left-mouse down
            .moveTo(null, 0, -100) // mouse-move -100 on the Y-axis
            .buttonUp() // left-mouse up
            .$apply(); // execute

LOL Good News!!!

WarningFeature rely on WebdriverIO, seems a bug need to be fixed, detail Issue.

Since version 0.0.13, ext will auto route apis for PC to mobile support apis, for example:

moveToObject(ele, x, y) + buttonDown() => touchDown(ele.left + x, ele.top + y)

more detail@event-driver-hooks.js. Then most of ur tests can run both sides of PC and mobile, Write once, run twice.

How it works

browser in karma-event-driver-ext is just a proxy to receive command. while a webdriverio-like api being called, proxy will format arguments received, for example, convert an argument which type is Element to unique query, then call $apply to sends drive-commands to socket server and wait for executing response.

webdriverio is used to drive the browser and simulate user-behavior.

Tips:

  • must not hard refresh karma test page [Chrome is fine, while firefox goes wrong unexpectedly]
  • must call $apply, a promise will be returned.
  • if Element has no id, event-drivers-hook js will assign a unique id to it automatically.
  • aim to simulate event and most webdriverio api support[except , $, then and all Window/api]. more api

requirements

then must export path to $PATH where u put drivers* or copy drivers* to project directory.

usage

npm install

karma.conf.js

module.exports = {
     customLaunchers: {
        'Chrome': {
            base: 'WebDriverio',
            browserName: 'chrome',
            name: 'Karma'
        },
        'Firefox': {
            base: 'WebDriverio',
            browserName: 'firefox',
            name: 'Karma-Firefox',
            config: {
                browserName: 'firefox',
                host: '127.0.0.1', // default
                port: '4444' // default
            }
        }
    },
    browsers: ['Chrome'],
    // if plugins assigned, should:
    // since with plugins, karma won't auto load karma-* modules
    plugins: [
        'karma-webdriverio-launcher'
    ]
    ...
}
basic usage
    import { beforeHook, beforeEachHook, afterHook, browser, config } from 'karma-event-driver-ext/cjs/event-driver-hooks';
    let { $serial } = browser;
    // ext using socket-io to communicate with webdriver-io, host & port is changeable
    config({
        host: 127.0.0.1, // default
        port: 8848       // default, if modified, keep same to init({ port: 8848 })
    });
    describe('Test', function() {
        // first increase timeout
        ...
        // then before all hook
        before(async () => {
            await beforeHook();
            ...
        })

        // required if using $serial
        beforeEach(async () => {
            await beforeEachHook();
        });

        after(async () => {
            ...
            await afterHook();
        })

        it('Example', async () => {
            await browser
                .click(document.body)
                .$apply();
            
            await browser
                .pause(1000)
                .$apply(); // wait 1000 ms
            ...
        })
    });
advanced usage

in specified situation, eg: React Component, tests won't start until componentDidMount trigger, More complex, will pause and wait for componentDidUpdate to resume.

always need wrapping a promise:

it('test', async () => {
    let rs, rj, prom = new Promise((s, j) => {
        rs = s;
        rj = j;
    })
    class A extends Component {
        ...

        componentDidMount() {
            rs();
        }

        componentDidUpdate() {
            rs();
        }

        click() {
            this.setState({
                reRender: true
            })
        }
        render() {
            return <div id="button">click me</div>
        }
        ...
    }
    let inst = ReactDom.render(<A/>, document.body);
    await prom;
    prom = new Promise((s, j) => {
        rs = s;
        rj = j;
    };
    await browser
        .click('#button')
        .$apply();
    await prom;
})

Ext makes a new way that use $serial api to wrap test in serial, then use browser.$next(status) to start/resume/reject and $apply('applyAndWaitForNext')/$applyAndWaitForNext() to pause test, $serial return a promise which will be resolved if all tests finished.

Instead of wrapping promise, u can:

    class A {
        ...
        componentDidMount() {
            browser.$next();
        }

        componentDidUpdate() {
            browser.$next();
        }
    }
    
    ReactDom.render(<A/>, document.body);

    // await or return, $serial return a promise
    return browser.$serial(
        async () => {
            await browser
                .click('#button')
                .$apply('applyAndWaitForNext');
        },
        async () => {
            await browser
                .click('#button')
                .$applyAndWaitForNext();
        }
    );

If browser.$next() ran before $serial, a resolved promise flag will be assigned to browser. then while calling $serial, if there is a resolved promised flag, serial tests will auto start.

Ensure calling beforeEachHook() in beforeEach if using $serial

    beforeEach(async () => {
        await beforeEachHook();
    });

And, once test broke, it won't resume util calling browser.$next()

   await browser
        .click(xxx)
        .$applyAndWaitForNext(); // or .$apply('applyAndWaitForNext');
   // pause here, util browser.$next()
   pausing code wait for next
   ...

Examples

Run Test:

cli

    // start selenium-server-standalone
    java -jar selenium-server-standalone-3.3.1.jar
    // start karma server && event-driver server
    node node_modules/karma-event-driver-ext
    // or 
    ./node_modules/.bin/karma-event-driver-ext

api: runner.js

    let ext, { init } = require('karma-event-driver-ext');
    let karmaServer = init({
        onExit: (exitCode) {
            console.log('exitCode',  exitCode);
        },
        port: 8848 // default, same to config({ port: 8848 })
    });
    node runner.js
    // or 
    ./node_modules/.bin/karma-event-driver-ext runner.js

    // or if npm install -g: ^0.0.10, ensure all dependencies installed -g.
    // karma-event-driver-ext runner.js