Code Monkey home page Code Monkey logo

blocking-proxy's Introduction

Blocking Proxy Build Status

Blocking Proxy is a tool for adding functionality to WebDriver-based tests. It sits between your tests and the Selenium Server. For each WebDriver command, it runs a set of 'barriers' that will block forwarding the command to the Selenium server until some condition is met.

Because it interacts with WebDriver at the network level, Blocking Proxy can be used regardless of which language your tests are written in. See the example for a demonstration of using Blocking Proxy with WebDriver tests written in Python.

Although Blocking Proxy can handle multiple WebDriver sessions, it can not yet handle multiple concurrent clients. Thus, it's recommended to start a separate instance for each test process.

Usage

Blocking Proxy can be installed globally with npm install -g blocking-proxy. You can also use it by cloning this repo and running these commands:

npm install
webdriver-manager update && webdriver-manager start (in another terminal)
node ./built/lib/bin.js --seleniumAddress http://localhost:4444/wd/hub

Features

Wait for Angular

When testing an Angular application, Blocking Proxy can block webdriver commands until Angular's change detection is finished, and thus make your tests less flaky.

Highlight Delay

If --highlightDelay <delayMS> is specified, Blocking Proxy will wait for the specified delay (in milliseconds) before executing click commands or sending keys. It will also highlight the element that is the target of the command.

Here's an example of highlight delay in action:

Highlight Delay

WebDriver logging

When --logDir <path> is set, Blocking Proxy will create a readable log of WebDriver commands at the specified path. The log will look something like this:

20:08:14.830 |    834ms | 37f13c | NewSession
    {"browserName":"chrome"}
20:08:15.674 |      4ms | 37f13c | SetTimeouts
20:08:15.681 |    578ms | 37f13c | Go http://localhost:8081/ng1/#/interaction
20:08:16.300 |    438ms | 37f13c | FindElement
    Using css selector \'.invalid\'
    ERROR: no such element

Each line shows the command that was executed and how long it took. For some commands, extra data or the response from WebDriver will be shown on following lines.

Development

Formatting and lint

gulp format runs clang-format. gulp lint validates format and runs tslint.

Running tests

Unit tests live in spec/unit and can be run with npm test. Run npm run test:auto to automatically watch for changes and run unit tests.

Running e2e tests

Start webdriver

webdriver-manager update
webdriver-manager start

in another terminal, start the testapp

npm run testapp 

Start the proxy with

npm start

in yet another terminal, run the tests

npm run test:e2e

blocking-proxy's People

Contributors

heathkit avatar juliemr avatar kuangp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blocking-proxy's Issues

Feature Request: Reduce waiting for Angular

The AngularWaitBarrier currently waits for Angular before each command. This is overkill. It could track whether the app is "dirty" or not by remembering if it's run waitForAngular since the most recent command that could have triggered Angular's change detection. This would include click, send keys, mouse actions, alert actions, and potentially executeScript calls.

Typescript definition file contains error

The Typescript definition file at built/lib/blockingproxy.d.ts contains the following line (line 6 I believe):

export declare const BP_PREFIX = "bpproxy";

This is not valid for a Typescript definition file (error: Initializers are not allowed in ambient contexts.). I believe the line should be:

export declare const BP_PREFIX: "bpproxy";

Implement highlightDelay

Add a runtime configuration option called highlightDelay. If set, the proxy will delay forwarding requests for the set number if milliseconds for any Find Element command (ie, any command ending in /element or /elements. During the delay, it will alter the background of the found elements to something visible.

Blockingproxy: TypeError: Cannot read property 'toString' of null

Originally reported here: angular/protractor#4473

I have been using some protractor scripts which have been running fine for a few months.

In the past week, I upgraded to:

  • Node Version: v8.4.0
  • Protractor Version: version 5.1.2
  • Browser(s): Chrome 61.0.3163.79
  • Chromedriver: 2.32
  • selenium standalone server: 3.5.3
  • Operating System and Version MacOS X and Windows

and suddenly I am getting this error in BlockingProxy:

BlockingProxy error: E/BlockingProxy - (node:26020) TypeError: Cannot read property 'toString' of null

I added the node --trace-warnings flag and got a stack trace:

 E/BlockingProxy - (node:26296) TypeError: Cannot read property 'toString' of null
    at replyWithError (/Users/c-craigr/work1/es-automation-test/ui-tests/node_modules/blocking-proxy/built/lib/webdriver_proxy.js:42:35)
    at WebDriverProxy.<anonymous> (/Users/c-craigr/work1/es-automation-test/ui-tests/node_modules/blocking-proxy/built/lib/webdriver_proxy.js:53:17)
    at Generator.throw (<anonymous>)
    at rejected (/Users/c-craigr/work1/es-automation-test/ui-tests/node_modules/blocking-proxy/built/lib/webdriver_proxy.js:5:62)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

I tracked the problem down to this code in BlockingProxy:

https://github.com/angular/blocking-proxy/blob/master/lib/webdriver_proxy.ts#L29

 let replyWithError = (err) => {
      response.writeHead(500);
      response.write(err.toString());
      response.end();
    };

In this case err is null, so that causes an exception to be thrown.

Does anybody have an idea why err is null?

Give highlight a high z-index

It seems like the highlight created by HIGHLIGHT_FN should have its z-index set to something sufficiently high to ensure it is above other elements on the page. I am using this on an Angular app using Angular Material and without setting the z-index for the highlighter it doesn't show up.

Documentation

Add proper documentation on how to install and use in the README

when calling protractor with --webDriverLogDir flag, throws an error

example

package.json

dependencies: typescript, ts-node, [email protected]

conf.js

exports.config = {
  seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
  specs: [ 'spec.ts' ],
  beforeLaunch: () => {
    require('ts-node').register({
      project: '.'
    });
  }
};

spec.ts (test fails to launch)

var env = {};
env.url = 'https://angular.github.io/protractor-cookbook/ng1/calculator/';

describe('slow calculator', () => {
  beforeEach(() => {
    browser.get(env.url + '/ng1/calculator/');
  });

  it('should add numbers', () => {
    element(by.model('first')).sendKeys('4');
    element(by.model('second')).sendKeys('5');
    element(by.id('gobutton')).click();

    expect(element(by.binding('latest')).getText()).toEqual('9');
  });
});

log

> protractor config.js --webDriverLogDir

[13:40:41] I/launcher - Running 1 instances of WebDriver
[13:40:41] I/hosted - Using the selenium server at http://127.0.0.1:4444/wd/hub
[13:40:41] I/BlockingProxy - Starting BlockingProxy with args: --fork,--seleniumAddress,http://127.0.0.1:4444/wd/hub,--logDir,true
[13:40:41] I/protractor - Starting BP client for http://localhost:63196
[13:40:41] E/BlockingProxy - events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: ENOENT: no such file or directory, open 'true/webdriver_log_3pzifwat.txt'
    at Error (native)
[13:40:41] E/BlockingProxy - Exited with 1
[13:40:41] E/BlockingProxy - signal null
[13:40:41] E/launcher - Error code: 135
[13:40:41] E/launcher - Error message: ECONNREFUSED connect ECONNREFUSED 127.0.0.1:63196
[13:40:41] E/launcher - Error: ECONNREFUSED connect ECONNREFUSED 127.0.0.1:63196
    at ClientRequest.<anonymous> (/Users/cnishina/src/protractor-cookbook/protractor-blockingproxy/node_modules/selenium-webdriver/http/index.js:238:15)
    at emitOne (events.js:96:13)
    at ClientRequest.emit (events.js:188:7)
    at Socket.socketErrorListener (_http_client.js:310:9)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at emitErrorNT (net.js:1278:8)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)
From: Task: WebDriver.createSession()
    at Function.createSession (/Users/cnishina/src/protractor-cookbook/protractor-blockingproxy/node_modules/selenium-webdriver/lib/webdriver.js:777:24)
    at Function.createSession (/Users/cnishina/src/protractor-cookbook/protractor-blockingproxy/node_modules/selenium-webdriver/chrome.js:709:29)
    at createDriver (/Users/cnishina/src/protractor-cookbook/protractor-blockingproxy/node_modules/selenium-webdriver/index.js:167:33)
    at Builder.build (/Users/cnishina/src/protractor-cookbook/protractor-blockingproxy/node_modules/selenium-webdriver/index.js:623:16)
    at Hosted.getNewDriver (/Users/cnishina/src/protractor-cookbook/protractor-blockingproxy/node_modules/protractor/lib/driverProviders/driverProvider.ts:60:29)
    at Runner.createBrowser (/Users/cnishina/src/protractor-cookbook/protractor-blockingproxy/node_modules/protractor/lib/runner.ts:225:39)
    at q.then.then (/Users/cnishina/src/protractor-cookbook/protractor-blockingproxy/node_modules/protractor/lib/runner.ts:391:27)
    at _fulfilled (/Users/cnishina/src/protractor-cookbook/protractor-blockingproxy/node_modules/q/q.js:834:54)
    at self.promiseDispatch.done (/Users/cnishina/src/protractor-cookbook/protractor-blockingproxy/node_modules/q/q.js:863:30)
    at Promise.promise.promiseDispatch (/Users/cnishina/src/protractor-cookbook/protractor-blockingproxy/node_modules/q/q.js:796:13)
[13:40:41] E/launcher - Process exited with error code 135

npm ERR! Darwin 16.3.0
npm ERR! argv "/Users/cnishina/.nvm/versions/node/v6.9.4/bin/node" "/Users/cnishina/.nvm/versions/node/v6.9.4/bin/npm" "run" "logs"
npm ERR! node v6.9.4
npm ERR! npm  v3.10.10
npm ERR! code ELIFECYCLE
npm ERR! [email protected] logs: `protractor config.js --webDriverLogDir`
npm ERR! Exit status 135
npm ERR!
npm ERR! Failed at the [email protected] logs script 'protractor config.js --webDriverLogDir'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the protractor-blockingproxy package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     protractor config.js --webDriverLogDir
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs protractor-blockingproxy
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls protractor-blockingproxy
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:

Clean up test apps

Test apps only need to include the waiting logic, and should probably be generated on-the-fly rather than checking in the compiled JS.

Feature Request: Consistent/specialized/faster error for `unload` events during stability wait

If a browser navigates to a new page while blocking proxy is waiting for a stability script to call its callback, an error will occur (either directly or because the callback never gets called). This makes sense enough, but has a few issues:

  1. Depending on the selenium server implementation, the text of the error message changes.
  2. If the navigation occurs between two WebDriverBarriers, or after the barriers but before the actual commend is run, you won't error at all but instead run the command with some/all of the barriers not being run. This is just wrong and we should get an error message instead.
  3. Some tools would like to be able to handle this kind of error. For example, angular/protractor#4052. However, because of the previous issues, it's hard to tell in a programatic way when you've run into this error. Blocking Proxy should have a custom error message that's easy for something like Protractor to identify (or provide a method for distinguish this error in BPClient).
  4. Some implementations may just let the command timeout. Waiting for a timeout should be unnecessary in this case, since Blocking Proxy should be able to see that the script timed out.

In angular/protractor#4053 I suggested Protractor deal with the same problem by using browser.driver.wait. Blocking Proxy could do something analogous.

'[ng:app] not a valid selector

I keep getting the following error on my tests:

Selenium::WebDriver::Error::WebDriverError:
       unexpected response, code=500, content-type=""
       Error: Error from waitForAngular: Failed to execute 'querySelectorAll' on 'Document': '[ng:app]' is not a valid selector.

I removed both trySelector('[ng:app]') and trySelector('[ng:controller]') in https://github.com/angular/blocking-proxy/blob/master/lib/client_scripts/wait.js#L111, and my tests are working now.

I don't know enough to say if those trySelector calls need to be there or not. But perhaps the method should also be surrounded by a try-catch like the tryEl method?

Allow setting sync scripts at run-time

Replace the setSynchronization API with something more sophisticated.

  • Allow users to specify which client-side blocking scripts to run with each webdriver command.
  • In addition to enabling/disabling scripts, allow changing the parameters (so Protractor can change rootEl)
  • Allow configuring the timeout for each script.
  • Potentially set a priority for the scripts, so they run in a defined order
  • Allow providing a path to the client side scripts as a command line option

This is needed for angular/protractor#3857 and angular/protractor#3858.

Set noImplicitAny true in tsconfig

It'll future proof things to have proper types everywhere. Also consider trying out strictNullChecks: true and see how much work it is.

Implement highlightDelay

Add a runtime configuration option called highlightDelay. If set, the proxy will delay forwarding requests for the set number if milliseconds for any Find Element command (ie, any command ending in /element or /elements. During the delay, it will alter the background of the found elements to something visible.

Incorrect "Host" header being forwarded in Selenium requests

I believe WebdriverProxy is incorrectly forwarding the Host header from originalRequest here: https://github.com/angular/blocking-proxy/blob/master/lib/webdriver_proxy.ts#L52

The headers from originalRequest includes the Host header which is set to the host of the blocking proxy server (eg. localhost:xxxxx). When this forwarded along in the request to selenium, some selenium servers can reject the request since the Host is unknown. I believe this should be explicitly omitted from options.headers so it will corrected be inserted by Node Http.

Does this work over ssl?

Hi, Ive been trying for a while to get this to work in our infrastructure. I tried with a selenium grid loccally over http and it works fine. However when i point it at our global selenium grid it doesnt seem to work. The only difference I can see is that the global grid is https.

Does this lib have any issues with https?

Add comprehensive logging

The proxy should be able to output extremely readable logs of webdriver actions and what it tried to add.

Per-session parameters

Waiting for angular and setting wait function params are currently global for the proxy. These params should be per-session, since we could be proxying different browser sessions.

This means:

  • proxy commands need to pass a session ID for non-global options (ie, everything other than seleniumAddress)
  • the proxy needs to keep track of webdriver sessions

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.