Esempio n. 1
0
 return flow.execute(function() {
   return webdriver.promise.fulfilled('setup done');
 });
Esempio n. 2
0
var setUpSelenium = function() {
  // TODO: This should not be tied to the webdriver promise loop, it should use
  // another promise system instead.
  var deferred = webdriver.promise.defer();

  if (config.sauceUser && config.sauceKey) {
    sauceAccount = new SauceLabs({
      username: config.sauceUser,
      password: config.sauceKey
    });
  }

  var defaultChromedriver;
  if (config.chromeDriver) {
    if (!fs.existsSync(config.chromeDriver)) {
      if (fs.existsSync(config.chromeDriver + '.exe')) {
        config.chromeDriver += '.exe';
      } else {
        throw 'Could not find chromedriver at ' + config.chromeDriver;
      }
    }
  } else {
    defaultChromedriver = path.resolve(__dirname,
        '../selenium/chromedriver');
    if (fs.existsSync(defaultChromedriver)) {
      config.chromeDriver = defaultChromedriver;
    } else if (fs.existsSync(defaultChromedriver + '.exe')) {
      config.chromeDriver = defaultChromedriver + '.exe';
    }
  }

  // Priority
  // 1) if chromeOnly, use that
  // 2) if seleniumAddress is given, use that
  // 3) if a sauceAccount is given, use that.
  // 4) if a seleniumServerJar is specified, use that
  // 5) try to find the seleniumServerJar in protractor/selenium
  if (config.chromeOnly) {
    util.puts('Using ChromeDriver directly...');
    deferred.fulfill(null);
  } else if (config.seleniumAddress) {
    util.puts('Using the selenium server at ' + config.seleniumAddress);
    deferred.fulfill(config.seleniumAddress);
  } else if (sauceAccount) {
    config.capabilities.username = config.sauceUser;
    config.capabilities.accessKey = config.sauceKey;
    if (!config.jasmineNodeOpts.defaultTimeoutInterval) {
      config.jasmineNodeOpts.defaultTimeoutInterval = 30 * 1000;
    }
    config.seleniumAddress = 'http://' + config.sauceUser + ':' +
        config.sauceKey + '@ondemand.saucelabs.com:80/wd/hub';

    util.puts('Using SauceLabs selenium server at ' + config.seleniumAddress);
    deferred.fulfill(config.seleniumAddress);
  } else {
    util.puts('Starting selenium standalone server...');

    if (!config.seleniumServerJar) {
      // Try to use the default location.
      var defaultStandalone = path.resolve(__dirname,
          '../selenium/selenium-server-standalone-' +
          require('../package.json').webdriverVersions.selenium + '.jar');
      if (!fs.existsSync(defaultStandalone)) {
        throw new Error('Unable to start selenium. ' +
        'You must specify either a seleniumAddress, ' +
        'seleniumServerJar, or saucelabs account, or use webdriver-manager.');
      } else {
        config.seleniumServerJar = defaultStandalone;
      }
    } else if (!fs.existsSync(config.seleniumServerJar)) {
      throw new Error('there\'s no selenium server jar at the specified '+
        'location. Do you have the correct version?');
    }

    if (config.chromeDriver) {
      config.seleniumArgs.push(
          '-Dwebdriver.chrome.driver=' + config.chromeDriver);
    }

    server = new remote.SeleniumServer(config.seleniumServerJar, {
      args: config.seleniumArgs,
      port: config.seleniumPort
    });
    server.start().then(function(url) {

      util.puts('Selenium standalone server started at ' + url);
      config.seleniumAddress = server.address();
      deferred.fulfill(config.seleniumAddress);
    });
  }

  return deferred.promise;
}
describe('video_hdmi small', function() {
  'use strict';

  var app = webdriver.promise.controlFlow();
  process_utils.injectWdAppLogging('WD app', app);

  var sandbox;
  var videoCommand = '/video/record';

  beforeEach(function() {
    sandbox = sinon.sandbox.create();

    test_utils.fakeTimers(sandbox);
    app.reset();  // We reuse the app across tests, clean it up.
  });

  afterEach(function() {
    // Call unfakeTimers before verifyAndRestore, which may throw.
    test_utils.unfakeTimers(sandbox);
    sandbox.verifyAndRestore();
  });

  it('should start and stop video recording', function() {
    var serial = 'GAGA123';
    var pid = 7;

    var fakeCaptureProc;
    var killCount = 0;
    var processSpawnStub = test_utils.stubOutProcessSpawn(sandbox);
    processSpawnStub.callback = function(proc, command, args) {
      if (videoCommand === command) {
        proc.pid = pid;
        fakeCaptureProc = proc;
        return true; // keep alive
      }
      var stdout;
      if ('ps' === command) {
        stdout = [
          '1 ' + pid + ' ' + videoCommand + ' -f x -s ' + serial + ' y',
          '1 ' + (pid + 100) + ' ignoreMe',
          pid + ' ' + (pid + 10) + ' raw_capture'
        ].join('\n');
      } else if ('kill' === command) {
        if (pid === parseInt(args[args.length - 1], 10) && fakeCaptureProc) {
          fakeCaptureProc.emit('exit', undefined, 'SIGAGA');
          fakeCaptureProc = undefined;
        }
        killCount += 1;
        stdout = '';
      } else {
        should.fail('Unexpected command: ' + command);
      }
      if (undefined !== stdout) {
        proc.stdout.emit('data', stdout);
      }
    };
    // Check for existence of the video record script
    var fsExistsStub = sandbox.stub(fs, 'exists', function(path, cb) {
      global.setTimeout(function() {
        cb(videoCommand === path);
      }, 1);
    });

    should.equal('[]', app.getSchedule());
    var videoFile = 'test.avi';
    var deviceType = 'shmantra';
    var videoCard = '2';

    var video = new video_hdmi.VideoHdmi(app, videoCommand);
    video.scheduleStartVideoRecording(videoFile, serial, deviceType, videoCard);
    test_utils.tickUntilIdle(app, sandbox);
    should.equal(2, killCount);
    processSpawnStub.assertCalls(
        {0: 'ps', 1: '-u', 2: /^\d+$/}, // Find our leftover capture pid
        {0: 'ps', 1: '-u', 2: /^\d+$/}, // Get the pid tree
        ['kill', '-9', ('' + pid)],
        ['kill', '-9', ('' + (pid + 10))],
        [videoCommand, '-f', videoFile, '-s', serial, '-t', deviceType, '-d',
            videoCard, '-w']);
    should.ok(fsExistsStub.calledOnce);

    // Watch for IDLE -- make sure the wait for recording exit has finished.
    should.equal('[]', app.getSchedule());
    video.scheduleStopVideoRecording();
    test_utils.tickUntilIdle(app, sandbox);
    processSpawnStub.assertCalls(
        {0: 'ps'},
        ['kill', '-9', ('' + pid)],
        ['kill', '-9', ('' + (pid + 10))]);
    should.equal(4, killCount);
    should.equal(undefined, fakeCaptureProc);
    processSpawnStub.assertCall();
  });
});
Esempio n. 4
0
 return this.findAll('input').then(function(els) {
   return Driver.promise.map(els, function(el) {
     return el.clear();
   });
 }).then(function() {
Esempio n. 5
0
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

require('./_bootstrap')(module);

var assert = require('assert'),
    webdriver = require('selenium-webdriver'),
    flow = webdriver.promise.controlFlow(),
    testing = require('selenium-webdriver/testing'),
    fileserver = require('./fileserver'),
    seleniumserver = require('./seleniumserver');


var Browser = {
  ANDROID: 'android',
  CHROME: 'chrome',
  IE: 'internet explorer',
  // Shorthand for IPAD && IPHONE when using the browsers predciate.
  IOS: 'iOS',
  IPAD: 'iPad',
  IPHONE: 'iPhone',
  FIREFOX: 'firefox',
  OPERA: 'opera',
Esempio n. 6
0
exports.run = function(runner, specs) {
  var JasmineRunner = require('jasmine');
  var jrunner = new JasmineRunner();
  /* global jasmine */

  require('jasminewd2').init(webdriver.promise.controlFlow(), webdriver);

  var jasmineNodeOpts = runner.getConfig().jasmineNodeOpts;

  // On timeout, the flow should be reset. This will prevent webdriver tasks
  // from overflowing into the next test and causing it to fail or timeout
  // as well. This is done in the reporter instead of an afterEach block
  // to ensure that it runs after any afterEach() blocks with webdriver tasks
  // get to complete first.
  var reporter = new RunnerReporter(runner);
  jasmine.getEnv().addReporter(reporter);

  // Add hooks for afterEach
  require('./setupAfterEach').setup(runner, specs);

  // Filter specs to run based on jasmineNodeOpts.grep and jasmineNodeOpts.invert.
  jasmine.getEnv().specFilter = function(spec) {
    var grepMatch = !jasmineNodeOpts ||
        !jasmineNodeOpts.grep ||
        spec.getFullName().match(new RegExp(jasmineNodeOpts.grep)) != null;
    var invertGrep = !!(jasmineNodeOpts && jasmineNodeOpts.invertGrep);
    if (grepMatch == invertGrep) {
      spec.disable();
    }
    return true;
  };

  // Run specs in semi-random order
  if (jasmineNodeOpts.random) {
    jasmine.getEnv().randomizeTests(true);

    // Sets the randomization seed if randomization is turned on
    if (jasmineNodeOpts.seed) {
      jasmine.getEnv().seed(jasmineNodeOpts.seed);
    }
  }

  return runner.runTestPreparer().then(function() {
    return q.promise(function(resolve, reject) {
      if (jasmineNodeOpts && jasmineNodeOpts.defaultTimeoutInterval) {
        jasmine.DEFAULT_TIMEOUT_INTERVAL = jasmineNodeOpts.defaultTimeoutInterval;
      }

      var originalOnComplete = runner.getConfig().onComplete;

      jrunner.onComplete(function(passed) {
        try {
          var completed = q();
          if (originalOnComplete) {
            completed = q(originalOnComplete(passed));
          }
          completed.then(function() {
            resolve({
              failedCount: reporter.failedCount,
              specResults: reporter.testResult
            });
          });
        } catch (err) {
          reject(err);
        }
      });

      jrunner.configureDefaultReporter(jasmineNodeOpts);
      jrunner.projectBaseDir = '';
      jrunner.specDir = '';
      jrunner.addSpecFiles(specs);
      jrunner.execute();
    });
  });
};
Esempio n. 7
0
	createWebSite() {
		var d = webdriver.promise.defer();
		this.driver.findElement( by.id( 'top-create-website-button' ) ).click();
		d.fulfill( true );
		return d.promise;
	}
Esempio n. 8
0
Protractor.prototype.pause = function(opt_debugPort) {
  // Patch in a function to help us visualize what's going on in the control
  // flow.
  webdriver.promise.ControlFlow.prototype.getControlFlowText = function() {
    var descriptions = [];

    var getDescriptions = function(frameOrTask, descriptions) {
      if (frameOrTask.getDescription) {
        var stacktrace = frameOrTask.snapshot_.getStacktrace();
        stacktrace = stacktrace ? stacktrace.join('\n').trim() : ''; 
        descriptions.push({
          description: frameOrTask.getDescription(),
          stack: helper.filterStackTrace(stacktrace)
        });
      } else {
        for (var i = 0; i < frameOrTask.children_.length; ++i) {
          getDescriptions(frameOrTask.children_[i], descriptions);
        }
      }
    };
    if (this.history_.length) {
      getDescriptions(this.history_[this.history_.length - 1], descriptions);
    }
    if (this.activeFrame_.getPendingTask()) {
      getDescriptions(this.activeFrame_.getPendingTask(), descriptions);
    }
    getDescriptions(this.activeFrame_.getRoot(), descriptions);
    var asString = '-- WebDriver control flow schedule \n';
    for (var i = 0; i < descriptions.length; ++i) {
      asString += ' |- ' + descriptions[i].description;
      if (descriptions[i].stack) {
        asString += '\n |---' + descriptions[i].stack.replace(/\n/g, '\n |---');
      }
      if (i != (descriptions.length - 1)) {
        asString += '\n';
      }
    }
    return asString;
  };

  if (opt_debugPort) {
    process.debugPort = opt_debugPort;
  }

  // Call this private function instead of sending SIGUSR1 because Windows.
  process._debugProcess(process.pid);

  var flow = webdriver.promise.controlFlow();
  var pausePromise = flow.execute(function() {
    log.puts('Starting WebDriver debugger in a child process. Pause is ' +
        'still beta, please report issues at github.com/angular/protractor');
    var nodedebug = require('child_process').
        fork(__dirname + '/debugger/wddebugger.js', [process.debugPort]);
    process.on('exit', function() {
      nodedebug.kill('SIGTERM');
    });
  });

  var vm_ = require('vm');
  var browserUnderDebug = this;

  // Helper used only by './debugger/wddebugger.js' to insert code into the
  // control flow. 
  // In order to achieve this, we maintain a promise at the top of the control
  // flow, so that we can insert frames into it.
  // To be able to simulate callback/asynchronous code, we poll this object 
  // for an result at every run of DeferredExecutor.execute. 
  this.dbgCodeExecutor_ = {
    execPromise_: pausePromise, // Promise pointing to current stage of flow.
    execPromiseResult_: undefined, // Return value of promise.
    execPromiseError_: undefined, // Error from promise.
    
    // A dummy repl server to make use of its completion function.
    replServer_: require('repl').start({
      input: {on: function() {}, resume: function() {}}, // dummy readable stream
      output: {write: function() {}} // dummy writable stream
    }),

    // Execute a function, which could yield a value or a promise, 
    // and allow its result to be accessed synchronously
    execute_: function(execFn_) {
      var self = this;
      self.execPromiseResult_ = self.execPromiseError_ = undefined;

      self.execPromise_ = self.execPromise_.
          then(execFn_).
          then(function(result) {
            self.execPromiseResult_ = result;
          }, function(err) {
            self.execPromiseError_ = err;
          });

      // This dummy command is necessary so that the DeferredExecutor.execute
      // break point can find something to stop at instead of moving on to the
      // next real command.
      self.execPromise_.then(function() {
        return browserUnderDebug.executeScript_('', 'empty debugger hook');
      });
    },

    // Execute a piece of code.
    execute: function(code) {
      var execFn_ = function() {
        // Run code through vm so that we can maintain a local scope which is
        // isolated from the rest of the execution. 
        return vm_.runInThisContext(code);
      };
      this.execute_(execFn_);
    },

    // Autocomplete for a line.
    complete: function(line) {
      var self = this;
      var execFn_ = function() {
        var deferred = webdriver.promise.defer();
        self.replServer_.complete(line, function(err, res) {
          deferred.fulfill(res, err);
        });
        return deferred;
      };
      this.execute_(execFn_);
    },

    // Code finished executing. 
    resultReady: function() {
      return !this.execPromise_.isPending();
    }, 

    // Get asynchronous results synchronously. 
    // This will throw if result is not ready. 
    getResult: function() {
      if (!this.resultReady()) {
        throw new Error('Result not ready');
      }
      if (this.execPromiseError_) {
        throw this.execPromiseError_;
      }
      
      return JSON.stringify(this.execPromiseResult_);
    }
  };

  flow.timeout(1000, 'waiting for debugger to attach');
};
describe('browser_android_chrome small', function() {
  'use strict';

  var app = webdriver.promise.controlFlow();
  process_utils.injectWdAppLogging('WD app', app);

  var sandbox;
  var spawnStub;
  var serverStub;
  var chromeApk = '/gaga/Chrome.apk';
  var serial = 'GAGA123';
  var videoCard = '2';

  /**
   * @param {Object} var_args
   */
  function assertAdbCall(var_args) { // jshint unused:false
    spawnStub.assertCall.apply(spawnStub, (0 === arguments.length ? [] :
        ['adb', '-s', serial].concat(Array.prototype.slice.call(arguments))));
  }

  function assertAdbCalls(var_args) { // jshint unused:false
    var i;
    for (i = 0; i < arguments.length; i += 1) {
      assertAdbCall.apply(undefined, arguments[i]);
    }
  }

  beforeEach(function() {
    sandbox = sinon.sandbox.create();

    test_utils.fakeTimers(sandbox);
    app.reset();  // We reuse the app across tests, clean it up.

    spawnStub = test_utils.stubOutProcessSpawn(sandbox);
    serverStub = test_utils.stubCreateServer(sandbox);
    sandbox.stub(fs, 'exists', function(path, cb) { cb(true); });
    sandbox.stub(fs, 'unlink', function(path, cb) { cb(); });
    sandbox.stub(fs, 'writeFile', function(path, data, cb) { cb(); });
    reset_();
  });

  afterEach(function() {
    should.equal('[]', app.getSchedule());
    // Call unfakeTimers before verifyAndRestore, which may throw.
    test_utils.unfakeTimers(sandbox);
    sandbox.verifyAndRestore();
  });

  it('should remove \\r\'s from adb binout', function() {
    // unit tests as pairs of hexIn: hexOut
    var in2out = {'12': '12', '': '', '0d': '0d', '0a': '0a', '0a0d': '0a0d',
        '0d0a': '0a', '0d0a0d0a' : '0a0a', '70d0a6': '70d0a6', 'ab0d': 'ab0d',
        '120d0a34': '120a34', '0d0a0d0aff0d0a0d0a': '0a0aff0a0a',
        '120d0a340d0a560d780d0d0a90': '120a340a560d780d0a90'
    };
    var adb_ = new adb.Adb();
    var hexIn;
    for (hexIn in in2out) {
      var hexOut = adb_.dos2unix(new Buffer(hexIn, 'hex')).toString('hex');
      should.equal(hexOut, in2out[hexIn], hexIn);
    }
  });

  it('should install on first run, start, get killed', function() {
    startBrowser_({deviceSerial: serial, runNumber: 1, chrome: chromeApk});
    killBrowser_();
  });

  it('should not install on a non-first run, start, get killed', function() {
    startBrowser_({deviceSerial: serial, runNumber: 2, chrome: chromeApk});
    killBrowser_();
  });

  it('should use PAC server', function() {
    startBrowser_({deviceSerial: serial, runNumber: 1, chrome: chromeApk,
        pac: 'function FindProxyForURL...'});
    killBrowser_();
  });

  it('should record video with the correct device type', function() {
    // Simulate adb shell getprop ro.product.device -> shmantra
    spawnStub.callback = function(proc, command, args) {
      if (/adb$/.test(command) && -1 !== args.indexOf('ro.product.device')) {
        global.setTimeout(function() {
          proc.stdout.emit('data', 'shmantra');
        }, 1);
        return false;
      } else {
        return true; // keep capture alive
      }
    };
    var videoStart = sandbox.stub(
        video_hdmi.VideoHdmi.prototype, 'scheduleStartVideoRecording');
    var videoStop = sandbox.stub(
        video_hdmi.VideoHdmi.prototype, 'scheduleStopVideoRecording');
    browser = new browser_android_chrome.BrowserAndroidChrome(app,
        {deviceSerial: serial, runNumber: 1, chrome: chromeApk,
        videoCard: videoCard});
    browser.scheduleStartVideoRecording('test.avi');
    sandbox.clock.tick(webdriver.promise.ControlFlow.EVENT_LOOP_FREQUENCY * 4);
    should.ok(spawnStub.calledOnce);
    should.ok(videoStart.calledOnce);
    test_utils.assertStringsMatch(
        ['test.avi', serial, 'shmantra', videoCard],
        videoStart.firstCall.args.slice(0, 4));
    should.ok(videoStop.notCalled);

    browser.scheduleStopVideoRecording();
    sandbox.clock.tick(webdriver.promise.ControlFlow.EVENT_LOOP_FREQUENCY * 4);
    should.ok(spawnStub.calledOnce);
    should.ok(videoStart.calledOnce);
    should.ok(videoStop.calledOnce);
  });

  //
  // BrowserAndroidChrome wrapper:
  //

  var args;
  var browser;
  var ncProc;

  function reset_() {
    args = undefined;
    browser = undefined;
  }

  function startBrowser_(argv) {
    should.equal(undefined, args);
    args = argv;

    ncProc = undefined;
    spawnStub.callback = function(proc, command, args) {
      if (/adb$/.test(command) && 'echo x' === args[args.length - 1]) {
        global.setTimeout(function() {
          proc.stdout.emit('data', 'x');
        }, 1);
        return false;
      }
      var isNetcat = (/adb$/.test(command) && args.some(function(arg) {
        return (/^while true; do nc /.test(arg));
      }));
      ncProc = (isNetcat ? proc : ncProc);
      return isNetcat; // keep alive
    };

    should.equal(undefined, browser);
    browser = new browser_android_chrome.BrowserAndroidChrome(app, args);
    should.equal('[]', app.getSchedule());
    should.ok(!browser.isRunning());

    browser.startBrowser();
    sandbox.clock.tick(webdriver.promise.ControlFlow.EVENT_LOOP_FREQUENCY * 34);
    assertAdbCall('shell', 'am', 'force-stop', /^com\.[\.\w]+/);
    if (1 === args.runNumber) {
      assertAdbCalls(
          ['uninstall', /com\.[\w\.]+/],
          ['install', '-r', chromeApk]);
    }
    if (args.pac) {
      assertAdbCall('push', /^[^\/]+\.pac_body$/, /^\/.*\/pac_body$/);
    }
    assertAdbCall('shell', 'su', '-c', 'echo x');
    if (args.pac) {
      assertAdbCall('shell', 'su', '-c',
          /^while true; do nc -l \d+ < \S+pac_body; done$/);
    }
    var flags = ['--disable-fre', '--enable-benchmarking',
        '--metrics-recording-only', '--enable-remote-debugging'];
    if (args.pac) {
      flags.push('--proxy-pac-url=http://127.0.0.1:80/from_netcat');
    }
    assertAdbCalls(
        ['shell', 'su', '-c', 'echo \\"chrome ' + flags.join(' ') +
            '\\" > /data/local/chrome-command-line'],
        ['shell', 'su', '-c',
            'rm /data/data/com.google.android.apps.chrome_dev/files/tab*'],
        ['shell', 'am', 'start', '-n', /^com\.[\.\w]+/, '-d', 'about:blank'],
        ['forward', /tcp:\d+/, /^\w+/]);
    assertAdbCall();
    should.ok(browser.isRunning());
    (browser.getDevToolsUrl() || '').should.match(new RegExp(
        '^http:\\\/\\\/localhost:(' + Object.keys(serverStub.ports).join('|') +
        ')\\\/json$'));
    should.equal(undefined, browser.getServerUrl());
    should.equal(!!ncProc, !!args.pac);
    assertAdbCall();
  }

  function killBrowser_() {
    should.exist(browser);
    browser.kill();
    sandbox.clock.tick(webdriver.promise.ControlFlow.EVENT_LOOP_FREQUENCY * 5);
    should.equal('[]', app.getSchedule());
    should.ok(!browser.isRunning());

    if (args.pac) {
      assertAdbCall('shell', 'rm', /^\/.*\/pac_body$/);
    }
    assertAdbCall('shell', 'am', 'force-stop', /^com\.[\.\w]+/);
    assertAdbCall();
    should.equal(undefined, browser.getServerUrl());
    should.equal(undefined, browser.getDevToolsUrl());
    if (args.pac) {
      should.ok(ncProc.kill.calledOnce);
    }
  }
});
Esempio n. 10
0
 isDisplayed: function() {
   return webdriver.promise.fulfilled(false);
 }
describe('process_utils small', function() {
  'use strict';

  var app = webdriver.promise.controlFlow();
  process_utils.injectWdAppLogging('WD app', app);

  var sandbox;

  before(function() {
    process_utils.setSystemCommands();
  });

  beforeEach(function() {
    sandbox = sinon.sandbox.create();
    test_utils.fakeTimers(sandbox);
    app.reset();
  });

  afterEach(function() {
    test_utils.unfakeTimers(sandbox);
    sandbox.verifyAndRestore();
  });

  it('should use webdriver promise workaround', function() {
    // Verify that webdriver's promise only returns a single callback arg.
    // We workaround this by passing an array for multiple args, but ideally
    // we'll simply our code when webdriver is fixed.
    var a, b;
    app.schedule('x', function() {
      var done = new webdriver.promise.Deferred();
      done.fulfill('a', 'b');
      return done;
    }).then(function(a2, b2) {
      a = a2;
      b = b2;
    });
    test_utils.tickUntilIdle(app, sandbox);
    should.equal('a', a);
    should.equal(undefined, b); // webdriver bug?!
  });

  /**
   * Test scheduleFunction.
   * @param {number} delay in seconds.
   * @param {Error=} err
   * @param {Object=} v1
   * @param {Object=} v2
   */
  function testAsync(delay, err, v1, v2) {
    function f(ferr, fv1, fv2, cb) {
      if (delay > 0) {
        global.setTimeout(function() {
          cb(ferr, fv1, fv2);
        }, delay);
      } else {
        cb(ferr, fv1, fv2);
      }
    }
    var rn = 0;
    var re, rv1, rv2;
    process_utils.scheduleFunction(app, 'x', f, err, v1, v2).then(
        function(cv1, cv2) {
      rn += 1;
      rv1 = cv1;
      rv2 = cv2;
    }, function(ce) {
      rn += 1;
      re = ce;
    });
    should.equal(0, rn);
    test_utils.tickUntilIdle(app, sandbox);
    should.equal(1, rn);
    should.equal(err, re);
    should.equal(v1, rv1);
    should.equal(v2, rv2);
  }

  it('should support async functions', function() {
    testAsync(0, undefined, 7);
    testAsync(3, undefined, 7);
    testAsync(0, new Error('x'));
    testAsync(3, new Error('x'));
    testAsync(0, undefined, ['x', 'y']);
  });

  it('should support async fs.exists', function() {
    // fs.exists invokes cb(exists) instead of cb(err, exists),
    // so this is special-cased in process_utils
    sandbox.stub(fs, 'exists', function(path, cb) {
      global.setTimeout(function() {
        cb(path === 'y');
      }, 1);
    });

    var exists;
    process_utils.scheduleFunction(app, 'x', fs.exists, 'y').then(function(v) {
      exists = v;
    });
    test_utils.tickUntilIdle(app, sandbox);
    should.equal(true, exists);

    exists = undefined;
    process_utils.scheduleFunction(app, 'x', fs.exists, 'n').then(function(v) {
      exists = v;
    });
    test_utils.tickUntilIdle(app, sandbox);
    should.equal(false, exists);
  });

  it('should create a ProcessInfo', function() {
    var processInfo = new process_utils.ProcessInfo('123 456 abc def');
    should.equal('123', processInfo.ppid);
    should.equal('456', processInfo.pid);
    should.equal('abc', processInfo.command);
    should.equal('def', processInfo.args.join(' '));

    // Moar whitespaces plz!
    processInfo = new process_utils.ProcessInfo('  123   456    abc   def');
    should.equal('123', processInfo.ppid);
    should.equal('456', processInfo.pid);
    should.equal('abc', processInfo.command);
    should.equal('def', processInfo.args.join(' '));
  });

  it('should kill all process in killProcesses', function() {
    var processInfos = [
        new process_utils.ProcessInfo('0 1 a'),
        new process_utils.ProcessInfo('0 2 b'),
        new process_utils.ProcessInfo('0 3 c'),
        new process_utils.ProcessInfo('0 4 d'),
        new process_utils.ProcessInfo('0 5 e')
      ];
    var numKilled = 0;
    var spawnStub = test_utils.stubOutProcessSpawn(sandbox);
    spawnStub.callback = function(proc, command) {
      logger.info('Stub spawn: %s', command);
      if ('kill' === command) {
        numKilled += 1;
      }
      return false;
    };

    process_utils.scheduleKillAll(app, 'killAll', processInfos);
    test_utils.tickUntilIdle(app, sandbox);
    should.equal(5, numKilled);
  });

  function testKillTree(pid, psOutput, expectedPidsToKill) {
    var actualPidsToKill = [];
    var spawnStub = test_utils.stubOutProcessSpawn(sandbox);
    spawnStub.callback = function(proc, command, args) {
      var stdout = '';
      if ('kill' === command && /^\d+$/.test(args[args.length - 1])) {
        var pid = args[args.length - 1]; // kill pid
        actualPidsToKill.push(parseInt(pid, 10));
      } else if ('ps' === command) {
        stdout = psOutput;
      } else {
        throw new Error('Unexpected command: ' + command);
      }
      global.setTimeout(function() {
        proc.stdout.emit('data', stdout);
      }.bind(this), 1);
      return false;
    };

    process_utils.scheduleKillTree(app, 'killTree', {'pid': pid});
    test_utils.tickUntilIdle(app, sandbox);
    should.equal(actualPidsToKill.toString(), expectedPidsToKill.toString());
  }

  it('should kill process and children', function() {
    testKillTree(7,
      (' 1    7  r0\n' +
       ' 7   12  r0/c0\n' +
       ' 1    3  r1\n' +
       '12  999  r0/c0/g0\n' +
       ' 7   34  r0/c1'),
      [7, 34, 12, 999]);
  });

  function testAllocPort(expectedPorts, usedPorts, randomSeed) {
    test_utils.stubRandom(sandbox, randomSeed);
    var serverStub = test_utils.stubCreateServer(sandbox);
    serverStub.ports = (usedPorts || {});
    process_utils.scheduleAllocatePort(app, 'alloc port');
    test_utils.tickUntilIdle(app, sandbox);
    should.equal(JSON.stringify(serverStub.ports),
       JSON.stringify(expectedPorts));
  }

  it('should allocate a port', function() {
    testAllocPort({4940: -1, 4941: 1});
  });

  it('should allocate a port (with retry)', function() {
    testAllocPort({4941: 1, 27225: 1, 27224: -1}, {4941: 1});
  });

  it('should iterate over JSON objects', function() {
    var props = [];
    var d = {a: 1, b: 2};
    process_utils.forEachRecursive(d, function(key, obj) {
      should.equal(d, obj);
      props.push(key);
    });
    test_utils.assertStringsMatch(['a', 'b'], props);

    props = [];
    d = {a: 1, b: {c: 2}};
    process_utils.forEachRecursive(d, function(key, obj) {
      if ('c' === key) {
        should.equal(d.b, obj);
      } else {
        should.equal(d, obj);
      }
      props.push(key);
    });
    test_utils.assertStringsMatch(['a', 'b', 'c'], props);

    // Empty map never calls the callback.
    process_utils.forEachRecursive({}, function() {
      throw new Error('Not supposed to be here');
    });

    // Non-map never calls the callback.
    process_utils.forEachRecursive('gaga', function() {
      throw new Error('Not supposed to be here');
    });
  });
});
Esempio n. 12
0
 return flow.execute(function() {
   return webdriver.promise.fulfilled(3.14159);
 });
Esempio n. 13
0
exports.getFakeDriver = function() {
  var flow = webdriver.promise.controlFlow();
  return {
    controlFlow: function() {
      return flow;
    },
    sleep: function(ms) {
      return flow.timeout(ms);
    },
    setUp: function() {
      return flow.execute(function() {
        return webdriver.promise.fulfilled('setup done');
      });
    },
    getValueA: function() {
      return flow.execute(function() {
        return webdriver.promise.delayed(500).then(function() {
          return webdriver.promise.fulfilled('a');
        });
      });
    },
    getOtherValueA: function() {
      return flow.execute(function() {
        return webdriver.promise.fulfilled('a');
      });
    },
    getValueB: function() {
      return flow.execute(function() {
        return webdriver.promise.fulfilled('b');
      });
    },
    getBigNumber: function() {
      return flow.execute(function() {
        return webdriver.promise.fulfilled(1111);
      });
    },
    getSmallNumber: function() {
      return flow.execute(function() {
        return webdriver.promise.fulfilled(11);
      });
    },
    getDecimalNumber: function() {
        return flow.execute(function() {
          return webdriver.promise.fulfilled(3.14159);
        });
      },
    getDisplayedElement: function() {
      return flow.execute(function() {
        return webdriver.promise.fulfilled({
          isDisplayed: function() {
            return webdriver.promise.fulfilled(true);
          }
        });
      });
    },
    getHiddenElement: function() {
      return flow.execute(function() {
        return webdriver.promise.fulfilled({
          isDisplayed: function() {
            return webdriver.promise.fulfilled(false);
          }
        });
      });
    }
  };
};
Esempio n. 14
0
 return webdriver.promise.delayed(500).then(function() {
   return webdriver.promise.fulfilled('a');
 });
Esempio n. 15
0
exports.stop = function() {
  var d = promise.defer();
  server.close(d.fulfill);
  return d.promise;
};
Esempio n. 16
0
Protractor.prototype.debugger = function() {
  // jshint debug: true
  this.driver.executeScript(clientSideScripts.installInBrowser);
  webdriver.promise.controlFlow().execute(function() { debugger; },
                                          'add breakpoint to control flow');
};
Esempio n. 17
0
            .then(function(viewportDecls) {
                // return all the metaviewports found
                webdriver.promise.map(
                    viewportDecls,
                    function(el) {
                        return el.getAttribute("content");
                    }
                ).then(
                    function(metaviewports) {
                        if (metaviewports === undefined ||
                            metaviewports.length === 0) {
                            checker.report("no-viewport-declared",
                                self.name, self.category);
                            return;
                        }
                        if (metaviewports.length > 1) {
                            checker.report("several-viewports-declared",
                                self.name,
                                self.category);
                        }
                        // the last one is the one used
                        var actualViewport = metaviewports[
                            metaviewports.length - 1];
                        var parsedViewport = metaparser.parseMetaViewPortContent(
                            actualViewport);
                        for (var prop in parsedViewport.invalidValues) {
                            checker.report("invalid-viewport-value", 
                                self.name,
                                self.category, {
                                    property: prop,
                                    value: parsedViewport.invalidValues[
                                        prop],
                                    validValues: metaparser.expectedValues[
                                        prop].join(", ")
                                });
                        }
                        if (!parsedViewport.validProperties.width &&
                            !parsedViewport.validProperties[
                                "initial-scale"]) {
                            checker.report("content-viewport-missed",
                                self.name,
                                self.category);
                        } else {
                            if (parsedViewport.validProperties.width) {
                                if (parsedViewport.validProperties.width ===
                                        "device-width" ||
                                    parsedViewport.validProperties.width ===
                                        "device-height") {
                                    //OK
                                    checker.sink.emit('done');
                                } else {
                                    checker.report("hardcoded-viewport-width",
                                        self.name, self.category);
                                }
                            }
                            if (parsedViewport.validProperties[
                                "initial-scale"]) {
                                //OK
                                checker.sink.emit('done');
                            }
                            if (parsedViewport.validProperties[
                                "user-scalable"] === "no") {
                                checker.report("users-are-prevented-to-zoom",
                                    self.name, self.category);
                            }
                            var unknownProperties = Object.keys(
                                parsedViewport.unknownProperties);
                            var nonstandardProperties =
                                unknownProperties.filter(
                                    function(i) {
                                        return wellknownMetaviewportProperties
                                            .indexOf(i) !== -1;
                                    }
                                );
                            var unrecognizedProperties =
                                unknownProperties.filter(
                                    function(i) {
                                        return wellknownMetaviewportProperties
                                            .indexOf(i) === -1;
                                    }
                                );
                            if (nonstandardProperties.length) {
                                checker.report(
                                    "non-standard-viewport-parameter-declared",
                                    self.name, self.category);
                            }
                            if (unrecognizedProperties.length) {
                                checker.report(
                                    "unknow-viewport-parameter-declared",
                                    self.name, self.category);
                            }
                        }

                    }
                );
            });
Esempio n. 18
0
			run: function(browserUtil, userUtil, pages){
				return promise.fulfilled().then(function(){ test(browserUtil, userUtil, pages); });
			}
Esempio n. 19
0
Protractor.prototype.pause = function() {
  // Patch in a function to help us visualize what's going on in the control
  // flow.
  webdriver.promise.ControlFlow.prototype.getControlFlowText = function() {
    var descriptions = [];

    var getDescriptions = function(frameOrTask, descriptions) {
      if (frameOrTask.getDescription) {
        var getRelevantStack = function(stack) {
          return stack.filter(function(line) {
            var include = true;
            for (var i = 0; i < STACK_SUBSTRINGS_TO_FILTER.length; ++i) {
              if (line.toString().indexOf(STACK_SUBSTRINGS_TO_FILTER[i]) !==
                  -1) {
                include = false;
              }
            }
            return include;
          });
        };
        descriptions.push({
          description: frameOrTask.getDescription(),
          stack: getRelevantStack(frameOrTask.snapshot_.getStacktrace())
        });
      } else {
        for (var i = 0; i < frameOrTask.children_.length; ++i) {
          getDescriptions(frameOrTask.children_[i], descriptions);
        }
      }
    };
    if (this.history_.length) {
      getDescriptions(this.history_[this.history_.length - 1], descriptions);
    }
    if (this.activeFrame_.getPendingTask()) {
      getDescriptions(this.activeFrame_.getPendingTask(), descriptions);
    }
    getDescriptions(this.activeFrame_.getRoot(), descriptions);
    var asString = '-- WebDriver control flow schedule \n';
    for (var i = 0; i < descriptions.length; ++i) {
      asString += ' |- ' + descriptions[i].description;
      if (descriptions[i].stack.length) {
        asString += '\n |---' + descriptions[i].stack.join('\n |---');
      }
      if (!(i == descriptions.length - 1)) {
        asString += '\n';
      }
    }
    return asString;
  };

  // Call this private function instead of sending SIGUSR1 because Windows.
  process._debugProcess(process.pid);
  var flow = webdriver.promise.controlFlow();

  flow.execute(function() {
    console.log('Starting WebDriver debugger in a child process. Pause is ' +
        'still beta, please report issues at github.com/angular/protractor');
    var nodedebug = require('child_process').
        fork(__dirname + '/wddebugger.js', ['localhost:5858']);
    process.on('exit', function() {
      nodedebug.kill('SIGTERM');
    })
  });
  flow.timeout(1000, 'waiting for debugger to attach');
};
Esempio n. 20
0
module.exports = function (jasmine) {

var webdriver = require('selenium-webdriver');

var flow = webdriver.promise.controlFlow();

/**
 * Wraps a function so that all passed arguments are ignored.
 * @param {!Function} fn The function to wrap.
 * @return {!Function} The wrapped function.
 */
function seal(fn) {
    return function () {
        fn();
    };
};

/**
 * Validates that the parameter is a function.
 * @param {Object} functionToValidate The function to validate.
 * @throws {Error}
 * @return {Object} The original parameter.
 */
function validateFunction(functionToValidate) {
    if (functionToValidate && Object.prototype.toString.call(functionToValidate) === '[object Function]') {
        return functionToValidate;
    } else {
        throw Error(functionToValidate + ' is not a function');
    }
}

/**
 * Validates that the parameter is a number.
 * @param {Object} numberToValidate The number to validate.
 * @throws {Error}
 * @return {Object} The original number.
 */
function validateNumber(numberToValidate) {
    if (!isNaN(numberToValidate)) {
        return numberToValidate;
    } else {
        throw Error(numberToValidate + ' is not a number');
    }
}

/**
 * Validates that the parameter is a string.
 * @param {Object} stringToValidate The string to validate.
 * @throws {Error}
 * @return {Object} The original string.
 */
function validateString(stringtoValidate) {
    if (typeof stringtoValidate == 'string' || stringtoValidate instanceof String) {
        return stringtoValidate;
    } else {
        throw Error(stringtoValidate + ' is not a string');
    }
}

/**
 * Wraps a function so it runs inside a webdriver.promise.ControlFlow and
 * waits for the flow to complete before continuing.
 * @param {!Function} globalFn The function to wrap.
 * @return {!Function} The new function.
 */
function wrapInControlFlow(globalFn, fnName) {
    return function () {
        var driverError = new Error();
        driverError.stack = driverError.stack.replace(/ +at.+jasminewd.+\n/, '');

        function asyncTestFn(fn, desc) {
            return function (done) {
                var desc_ = 'Asynchronous test function: ' + fnName + '(';
                if (desc) {
                    desc_ += '"' + desc + '"';
                }
                desc_ += ')';

                // deferred object for signaling completion of asychronous function within globalFn
                var asyncFnDone = webdriver.promise.defer();

                if (fn.length == 0) {
                    // function with globalFn not asychronous
                    asyncFnDone.fulfill();
                } else if (fn.length > 1) {
                    throw Error('Invalid # arguments (' + fn.length + ') within function "' + fnName + '"');
                }

                var flowFinished = flow.execute(function () {
                    var env = jasmine.getEnv();
                    fn.call(env.currentSpec, function (userError) {
                        if (userError) {
                            asyncFnDone.reject(new Error(userError));
                        } else {
                            asyncFnDone.fulfill();
                        }
                    });
                }, desc_);

                webdriver.promise.all([asyncFnDone, flowFinished]).then(function () {
                    seal(done)();
                }, function (e) {
                    e.stack = e.stack + '==== async task ====\n' + driverError.stack;
                    done(e);
                });
            };
        };

        var description, func, timeout;
        switch (fnName) {
            case 'it':
            case 'iit':
                description = validateString(arguments[0]);
                func = validateFunction(arguments[1]);
                if (!arguments[2]) {
                    globalFn(description, asyncTestFn(func));
                } else {
                    timeout = validateNumber(arguments[2]);
                    globalFn(description, asyncTestFn(func), timeout);
                }
                break;
            case 'beforeEach':
            case 'afterEach':
                func = validateFunction(arguments[0]);
                if (!arguments[1]) {
                    globalFn(asyncTestFn(func));
                } else {
                    timeout = validateNumber(arguments[1]);
                    globalFn(asyncTestFn(func), timeout);
                }
                break;
            default:
                throw Error('invalid function: ' + fnName);
        }
    };
};

global.it = wrapInControlFlow(global.it, 'it');
global.iit = wrapInControlFlow(global.iit, 'iit');
global.beforeEach = wrapInControlFlow(global.beforeEach, 'beforeEach');
global.afterEach = wrapInControlFlow(global.afterEach, 'afterEach');


/**
 * Wrap a Jasmine matcher function so that it can take webdriverJS promises.
 * @param {!Function} matcher The matcher function to wrap.
 * @param {webdriver.promise.Promise} actualPromise The promise which will
 *     resolve to the actual value being tested.
 * @param {boolean} not Whether this is being called with 'not' active.
 */
function wrapMatcher(matcher, actualPromise, not) {
    return function () {
        var originalArgs = arguments;
        var matchError = new Error("Failed expectation");
        matchError.stack = matchError.stack.replace(/ +at.+jasminewd.+\n/, '');
        actualPromise.then(function (actual) {
            var expected = originalArgs[0];

            var expectation = expect(actual);
            if (not) {
                expectation = expectation.not;
            }
            var originalAddMatcherResult = expectation.spec.addMatcherResult;
            var error = matchError;
            expectation.spec.addMatcherResult = function (result) {
                result.trace = error;
                jasmine.Spec.prototype.addMatcherResult.call(this, result);
            };

            if (expected instanceof webdriver.promise.Promise) {
                if (originalArgs.length > 1) {
                    throw error('Multi-argument matchers with promises are not '
                        + 'supported.');
                }
                expected.then(function (exp) {
                    expectation[matcher].apply(expectation, [exp]);
                    expectation.spec.addMatcherResult = originalAddMatcherResult;
                });
            } else {
                expectation.spec.addMatcherResult = function (result) {
                    result.trace = error;
                    originalAddMatcherResult.call(this, result);
                }
                expectation[matcher].apply(expectation, originalArgs);
                expectation.spec.addMatcherResult = originalAddMatcherResult;
            }
        });
    };
};

/**
 * Return a chained set of matcher functions which will be evaluated
 * after actualPromise is resolved.
 * @param {webdriver.promise.Promise} actualPromise The promise which will
 *     resolve to the acutal value being tested.
 */
function promiseMatchers(actualPromise) {
    var promises = { not: {} };
    var env = jasmine.getEnv();
    var matchersClass = env.currentSpec.matchersClass || env.matchersClass;

    for (matcher in matchersClass.prototype) {
        promises[matcher] = wrapMatcher(matcher, actualPromise, false);
        promises.not[matcher] = wrapMatcher(matcher, actualPromise, true);
    };

    return promises;
};

var originalExpect = global.expect;

global.expect = function (actual) {
    if (actual instanceof webdriver.promise.Promise) {
        if (actual instanceof webdriver.WebElement) {
            throw 'expect called with WebElement argument, expected a Promise. ' +
                'Did you mean to use .getText()?';
        }
        return promiseMatchers(actual);
    } else {
        return originalExpect(actual);
    }
};

// Wrap internal Jasmine function to allow custom matchers
// to return promises that resolve to truthy or falsy values
var originalMatcherFn = jasmine.Matchers.matcherFn_;
jasmine.Matchers.matcherFn_ = function (matcherName, matcherFunction) {
    var matcherFnThis = this;
    var matcherFnArgs = jasmine.util.argsToArray(arguments);
    return function () {
        var matcherThis = this;
        var matcherArgs = jasmine.util.argsToArray(arguments);
        var result = matcherFunction.apply(this, arguments);

        if (result instanceof webdriver.promise.Promise) {
            result.then(function (resolution) {
                matcherFnArgs[1] = function () {
                    return resolution;
                };
                originalMatcherFn.apply(matcherFnThis, matcherFnArgs).
                    apply(matcherThis, matcherArgs);
            });
        } else {
            originalMatcherFn.apply(matcherFnThis, matcherFnArgs).
                apply(matcherThis, matcherArgs);
        }
    };
};

/**
 * A Jasmine reporter which does nothing but execute the input function
 * on a timeout failure.
 */
var OnTimeoutReporter = function (fn) {
    this.callback = fn;
};

OnTimeoutReporter.prototype.reportRunnerStarting = function () { };
OnTimeoutReporter.prototype.reportRunnerResults = function () { };
OnTimeoutReporter.prototype.reportSuiteResults = function () { };
OnTimeoutReporter.prototype.reportSpecStarting = function () { };
OnTimeoutReporter.prototype.reportSpecResults = function (spec) {
    if (!spec.results().passed()) {
        var result = spec.results();
        var failureItem = null;

        var items_length = result.getItems().length;
        for (var i = 0; i < items_length; i++) {
            if (result.getItems()[i].passed_ === false) {
                failureItem = result.getItems()[i];

                if (failureItem.toString().match(/timeout/)) {
                    this.callback();
                }
            }
        }
    }
};
OnTimeoutReporter.prototype.log = function () { };

// On timeout, the flow should be reset. This will prevent webdriver tasks
// from overflowing into the next test and causing it to fail or timeout
// as well. This is done in the reporter instead of an afterEach block
// to ensure that it runs after any afterEach() blocks with webdriver tasks
// get to complete first.
jasmine.getEnv().addReporter(new OnTimeoutReporter(function () {
    flow.reset();
}));

};
			.then( products => promise.fullyResolved( products.map( e => e.getText() ) ) );
Esempio n. 22
0
 }, function (err) {
     var timeout;
     if (/asynchronous script timeout/.test(err.message)) {
         // Timeout on Chrome
         timeout = /-?[\d\.]*\ seconds/.exec(err.message);
     }
     else if (/Timed out waiting for async script/.test(err.message)) {
         // Timeout on Firefox
         timeout = /-?[\d\.]*ms/.exec(err.message);
     }
     else if (/Timed out waiting for an asynchronous script/.test(err.message)) {
         // Timeout on Safari
         timeout = /-?[\d\.]*\ ms/.exec(err.message);
     }
     if (timeout) {
         var errMsg_1 = 'Timed out waiting for Protractor to synchronize with ' +
             'the page after ' + timeout + '. Please see ' +
             'https://github.com/angular/protractor/blob/master/docs/faq.md';
         if (description.indexOf(' - Locator: ') == 0) {
             errMsg_1 +=
                 '\nWhile waiting for element with locator' + description;
         }
         var pendingTimeoutsPromise = void 0;
         if (_this.trackOutstandingTimeouts_) {
             pendingTimeoutsPromise = _this.executeScriptWithDescription('return window.NG_PENDING_TIMEOUTS', 'Protractor.waitForAngular() - getting pending timeouts' +
                 description);
         }
         else {
             pendingTimeoutsPromise = selenium_webdriver_1.promise.fulfilled({});
         }
         var pendingHttpsPromise = _this.executeScriptWithDescription(clientSideScripts.getPendingHttpRequests, 'Protractor.waitForAngular() - getting pending https' +
             description, _this.rootEl);
         return selenium_webdriver_1.promise
             .all([pendingTimeoutsPromise, pendingHttpsPromise])
             .then(function (arr) {
             var pendingTimeouts = arr[0] || [];
             var pendingHttps = arr[1] || [];
             var key, pendingTasks = [];
             for (key in pendingTimeouts) {
                 if (pendingTimeouts.hasOwnProperty(key)) {
                     pendingTasks.push(' - $timeout: ' + pendingTimeouts[key]);
                 }
             }
             for (key in pendingHttps) {
                 pendingTasks.push(' - $http: ' + pendingHttps[key].url);
             }
             if (pendingTasks.length) {
                 errMsg_1 += '. \nThe following tasks were pending:\n';
                 errMsg_1 += pendingTasks.join('\n');
             }
             err.message = errMsg_1;
             throw err;
         }, function () {
             err.message = errMsg_1;
             throw err;
         });
     }
     else {
         throw err;
     }
 });
Esempio n. 23
0
 execute: (command) => {
     command.setParameter('sessionId', sessionId);
     let params = command.getParameters();
     return webdriver.promise.fulfilled(execCallback(buildPath(paths[command.getName()], params), methods[command.getName()], params));
 },
Esempio n. 24
0
 ProtractorBrowser.prototype.get = function (destination, opt_timeout) {
     var _this = this;
     var timeout = opt_timeout ? opt_timeout : this.getPageTimeout;
     destination = this.baseUrl.indexOf('file://') === 0 ?
         this.baseUrl + destination :
         url.resolve(this.baseUrl, destination);
     var msg = function (str) {
         return 'Protractor.get(' + destination + ') - ' + str;
     };
     if (this.ignoreSynchronization) {
         this.driver.get(destination);
         return this.driver.controlFlow().execute(function () {
             return _this.plugins_.onPageLoad();
         });
     }
     var deferred = webdriver.promise.defer();
     this.driver.get(this.resetUrl).then(null, deferred.reject);
     this.executeScriptWithDescription('window.name = "' + DEFER_LABEL + '" + window.name;' +
         'window.location.replace("' + destination + '");', msg('reset url'))
         .then(null, deferred.reject);
     // We need to make sure the new url has loaded before
     // we try to execute any asynchronous scripts.
     this.driver
         .wait(function () {
         return _this
             .executeScriptWithDescription('return window.location.href;', msg('get url'))
             .then(function (url) {
             return url !== _this.resetUrl;
         }, function (err) {
             if (err.code == 13) {
                 // Ignore the error, and continue trying. This is
                 // because IE driver sometimes (~1%) will throw an
                 // unknown error from this execution. See
                 // https://github.com/angular/protractor/issues/841
                 // This shouldn't mask errors because it will fail
                 // with the timeout anyway.
                 return false;
             }
             else {
                 throw err;
             }
         });
     }, timeout, 'waiting for page to load for ' + timeout + 'ms')
         .then(null, deferred.reject);
     this.driver.controlFlow().execute(function () {
         return _this.plugins_.onPageLoad();
     });
     // Make sure the page is an Angular page.
     this.executeAsyncScript_(clientSideScripts.testForAngular, msg('test for angular'), Math.floor(timeout / 1000), this.ng12Hybrid)
         .then(function (angularTestResult) {
         var angularVersion = angularTestResult.ver;
         if (!angularVersion) {
             var message = angularTestResult.message;
             throw new Error('Angular could not be found on the page ' + destination +
                 ' : ' + message);
         }
         return angularVersion;
     }, function (err) {
         throw new Error('Error while running testForAngular: ' + err.message);
     })
         .then(loadMocks, deferred.reject);
     var self = this;
     function loadMocks(angularVersion) {
         if (angularVersion === 1) {
             // At this point, Angular will pause for us until
             // angular.resumeBootstrap
             // is called.
             var moduleNames = [];
             var _loop_1 = function(i) {
                 var mockModule = self.mockModules_[i];
                 var name_1 = mockModule.name;
                 moduleNames.push(name_1);
                 var executeScriptArgs = [
                     mockModule.script, msg('add mock module ' + name_1)
                 ].concat(mockModule.args);
                 self.executeScriptWithDescription.apply(self, executeScriptArgs)
                     .then(null, function (err) {
                     throw new Error('Error while running module script ' + name_1 + ': ' +
                         err.message);
                 })
                     .then(null, deferred.reject);
             };
             for (var i = 0; i < self.mockModules_.length; ++i) {
                 _loop_1(i);
             }
             self.executeScriptWithDescription('angular.resumeBootstrap(arguments[0]);', msg('resume bootstrap'), moduleNames)
                 .then(null, deferred.reject);
         }
         else {
             // TODO: support mock modules in Angular2. For now, error if someone
             // has tried to use one.
             if (self.mockModules_.length > 1) {
                 deferred.reject('Trying to load mock modules on an Angular2 app ' +
                     'is not yet supported.');
             }
         }
     }
     this.driver.controlFlow().execute(function () {
         return self.plugins_.onPageStable().then(function () {
             deferred.fulfill();
         }, function (error) {
             deferred.reject(error);
         });
     });
     return deferred.promise;
 };
Esempio n. 25
0
Runner.prototype.controlFlow = function() {
  return webdriver.promise.controlFlow();
};
var Browser = function(config) {
    var display, uaHeader, trackNetwork, browsermobProxy, proxy, driver,
    tmpdir, uadir;
    var chromeservice;
    var networkDataGatheringDone = function() {};
    var pendingNetworkDataGathering = 0;
    var self = this;
    var flow = webdriver.promise.controlFlow();
    var driverPromise = new webdriver.promise.Deferred();

    function init() {
        config = config || {};
        self.webdriver = webdriver;
        self.viewport = {};
        self.width = config.browserWidth || 320;
        self.height = config.browserHeight || 480;
        self.desktopWidth = config.browserDekstopWidth || self.width * 3;
        self.desktopHeight = config.browserDekstopHeight || self.height * 3;
        display = config.displayServer || 0;
        uaHeader = config.uaHeader || "";
        tmpdir = config.tmpdir || "/tmp";
        uadir = tmpdir + "/mobile-checker-" + uuid.v4();
        trackNetwork = config.trackNetwork || false;
        browsermobProxy = config.browsermobProxy || {
            'host': 'localhost',
            'port': 8080
        };
    }

    function setupProxy() {
        var Proxy = require('browsermob-proxy').Proxy;
        proxy = new Proxy({
            port: browsermobProxy.port,
            host: browsermobProxy.host
        });
    }

    function setupBrowser(proxyAddr) {
        var chromedriver = require("chromedriver");
        var chrome = require("selenium-webdriver/chrome");
        var proxy = require('selenium-webdriver/proxy');
        var capabilities = webdriver.Capabilities.chrome();

        if (proxyAddr) {
            var proxyPrefs = proxy.manual({
                http: proxyAddr,
                https: proxyAddr
            });
            capabilities.set(webdriver.Capability.PROXY, proxyPrefs);
        }

        // enabling metaviewport
        var options = new chrome.Options();
        //options.addArguments(["--enable-viewport-meta"]);
        options.addArguments(["--user-data-dir=" + uadir]);

        if (uaHeader) {
            options.addArguments(['--user-agent=' + uaHeader]);
        }
        options.addArguments(['--disable-bundled-ppapi-flash']);
        options.setUserPreferences({"session.startup_urls": ["about:blank"],
                                   "session.restore_on_startup": 4});
        capabilities.merge(options.toCapabilities());

        options.detachDriver(false);
        process.env.DISPLAY = ':' + display;
        chromeservice = new chrome.ServiceBuilder(chromedriver.path)
            .withEnvironment(process.env)
            .build();
        driver = new chrome.Driver(capabilities, chromeservice);
    }

    function get(url, done) {
        var time = Date.now();
        return driver.get(url).then(function() {
            time = Date.now() - time;
            self.emit('pageSpeed', time);
        }).then(function() {
            return dontGiveUpOnModal(function(d) {
                return setViewPort(d);
            }, driver);
        });
    }

    function reportNetworkTraffic(err, har) {
        var data;
        if (err) {
            self.emit('error', new Error(
                "Failed gathering network traffic: " + err));
            return;
        }
        try {
            data = JSON.parse(har);
        } catch (e) {
            self.emit('error', new Error(
                "Failed to parse network traffic data from proxy"));
            return;
        }
        pendingNetworkDataGathering = EventEmitter.listenerCount(self, 'har');

        self.emit('har', data, finishNetworkTrafficReport);
        if (pendingNetworkDataGathering === 0) {
            self.emit('networkdone');
        }
    }

    function finishNetworkTrafficReport() {
        pendingNetworkDataGathering--;
        if (pendingNetworkDataGathering === 0) {
            self.emit('networkdone');
            pendingNetworkDataGathering = null;
        }
    }

    // dontGiveUp from https://gist.github.com/domenic/2936696
    // we need to protect any code sent to the drivder
    // from UnexpectedAlertOpenError
    // we dismiss alerts 10 times at most
    function dontGiveUpOnModal(f, d, count) {
        if (!count) {
            count = 10;
        }
        return f(d).then(
            undefined, // pass through success
            function(err) {
                if (err.name === "UnexpectedAlertOpenError" && count >
                    0) {
                    // dismiss alert and retry
                    var alert = d.switchTo().alert();
                    alert.getText().then(function(text) {
                        self.emit('alert', text);
                    });
                    return alert.dismiss().then(function() {
                        dontGiveUpOnModal(f, d, count - 1);
                    });
                }
                self.emit('error', err);
                self.close();
            }
        );
    }


    function setViewPort(d) {
        var contentAttr;
        return d.findElements(webdriver.By.css('meta[name="viewport"]')).then(
            function(viewportDecls) {
                // return all the metaviewports found
                webdriver.promise.map(
                    viewportDecls,
                    function(el) {
                        return el.getAttribute("content");
                    }
                ).then(
                    function(contentAttrs) {
                        contentAttr = contentAttrs[contentAttrs.length -
                            1];
                    }
                );
            }).then(function() {
            if (contentAttr) {
                var viewportProps = metaparser.parseMetaViewPortContent(
                    contentAttr);
                self.viewport = metaparser.getRenderingDataFromViewport(
                    viewportProps.validProperties, self.width, self
                    .height, 4, 0.25);
            } else {
                self.viewport = {
                    zoom: null,
                    width: self.desktopWidth,
                    height: self.desktopHeight
                };
            }
            return d.manage().window().setSize(
                self.viewport.width,
                self.viewport.height + 97 //97px for the browser UI
            );
        }).then(function() {
            return d.executeScript(function() {
                // remove scrollbar
                // TODO webkit specific

                var style = document.createElement("style");
                var cssNoScrollbar = document.createTextNode(
                    "::-webkit-scrollbar { width: 0; height: 0;} body { overflow: hidden}"
                );
                style.appendChild(cssNoScrollbar);
                document.getElementsByTagName("head")[0].appendChild(
                    style);
            }).then(driverPromise.fulfill(d));
        });
    }

    this.close = function(processToKill) {
        return self.do(function(d) {
            var p = new webdriver.promise.Promise(function(res, rej) {
                networkDataGatheringDone();
                self.on('networkdone', res);
            }).then(function() {
                self.emit('done');
                return d.close().then(d.quit.bind(d)).then(chromeservice.stop.bind(chromeservice)).then(function() {
                    rimraf(uadir, function () {});
                    processToKill.kill();
                });
            });
            return p;
        });
    };

    this.open = function(url) {
        if (trackNetwork) {
            setupProxy();
            var setupProxyAndGet = function() {
                return function(proxyAddr, done) {
                    setupBrowser(proxyAddr);
                    networkDataGatheringDone = done;
                    flow.execute(function() {
                        get(url);
                    });
                };
            };
            flow.execute(function() {
                proxy.cbHAR({
                    name: url,
                    captureHeaders: true,
                    captureContent: true,
                    captureBinaryContent: true
                }, setupProxyAndGet(), reportNetworkTraffic);
            });
        } else {
            setupBrowser();
            return get(url);
        }
    };

    this.do = function(fn) {
        return driverPromise.then(function(d) {
            return dontGiveUpOnModal(function() {
                return flow.execute(
                    function() {
                        fn(d);
                    });
            }, d);
        });
    };

    this.takeScreenshot = function(path) {
        return self.do(function(d) {
            d.takeScreenshot().then(function(data) {
                var base64Data = data.replace(
                    /^data:image\/png;base64,/, "");
                fs.writeFile(path, base64Data, 'base64',
                    function(err) {
                        if (err) {
                            self.emit('error', err);
                        } else {
                            console.log(path);
                            // resize the screenshot
                            easyimg.resize({
                                src: path,
                                dst: path,
                                width: self.width,
                                height: self.height
                            })
                                .then(function() {
                                    self.emit('screenshot',
                                        path);
                                }, function(err) {
                                    console.log(err);
                                    self.emit('error', err);
                                });
                        }
                    });
            });
        });
    };

    init();
};
Esempio n. 27
0
var runJasmineTests = function() {
  if (config.jasmineNodeOpts.specFolders) {
    throw new Error('Using config.jasmineNodeOpts.specFolders is deprecated ' +
        'since Protractor 0.6.0. Please switch to config.specs.');
  }
  var specs = config.specs;
  if (!specs || specs.length == 0) {
    throw new Error('No spec files found.');
  }
  var resolvedSpecs = [];
  for (var i = 0; i < specs.length; ++i) {
    var matches = glob.sync(specs[i], {cwd: config.configDir});
    if (!matches.length) {
      util.puts('Warning: pattern ' + specs[i] + ' did not match any files.');
    }
    for (var j = 0; j < matches.length; ++j) {
      resolvedSpecs.push(path.resolve(config.configDir, matches[j]));
    }
  }
  if (!resolvedSpecs.length) {
    throw new Error('Spec patterns did not match any files.');
  }

  minijn.addSpecs(resolvedSpecs);
  // TODO: This should not be tied to the webdriver promise loop, it should use
  // another promise system instead.
  var runDeferred = webdriver.promise.defer();

  if (config.chromeOnly) {
    var service = new chrome.ServiceBuilder(config.chromeDriver).build();
    driver = chrome.createDriver(
        new webdriver.Capabilities(config.capabilities), service);
  } else {
    driver = new webdriver.Builder().
        usingServer(config.seleniumAddress).
        withCapabilities(config.capabilities).build();
  }

  driver.getSession().then(function(session) {
    driver.manage().timeouts().setScriptTimeout(config.allScriptsTimeout);

    sessionId = session.getId();

    var browser = protractor.wrapDriver(
        driver,
        config.baseUrl,
        config.rootElement)
    browser.params = config.params;

    protractor.setInstance(browser);

    // Export protractor to the global namespace to be used in tests.
    global.protractor = protractor;
    global.browser = browser;
    global.$ = browser.$;
    global.$$ = browser.$$;
    global.element = browser.element;
    global.by = protractor.By;

    // Let the configuration configure the protractor instance before running
    // the tests.
    webdriver.promise.controlFlow().execute(function() {
      if (config.onPrepare) {
        if (typeof config.onPrepare == 'function') {
          config.onPrepare();
        } else if (typeof config.onPrepare == 'string') {
          require(path.resolve(config.configDir, config.onPrepare));
        } else {
          throw 'config.onPrepare must be a string or function';
        }
      }
    }).then(function() {
      var options = config.jasmineNodeOpts;
      var originalOnComplete = options.onComplete;
      options.onComplete = function(runner, log) {
        if (originalOnComplete) {
          originalOnComplete(runner, log);
        }
        driver.quit().then(function() {
          runDeferred.fulfill(runner);
        });
      };

      minijn.executeSpecs(options);
    });
  });

  return runDeferred.promise;
};
Esempio n. 28
0
 return promise.when(port, function(port) {
   console.log('starting file server on ' + port);
   return promise.checkedNodeCall(
       server.listen.bind(server, port, 'localhost'));
 });
Esempio n. 29
0
export function deleteFile( fileDetails ) {
	var d = webdriver.promise.defer();
	fs.deleteSync( fileDetails.file );
	d.fulfill( true );
	return d.promise;
}
describe('web_page_replay small', function() {
  'use strict';

  var app = webdriver.promise.controlFlow();
  process_utils.injectWdAppLogging('WD app', app);

  var sandbox;
  var callNumber;

  beforeEach(function() {
    sandbox = sinon.sandbox.create();

    test_utils.fakeTimers(sandbox);
    app.reset();  // We reuse the app across tests, clean it up.

    callNumber = 0;
  });

  afterEach(function() {
    // Call unfakeTimers before verifyAndRestore, which may throw.
    should.equal('[]', app.getSchedule());
    test_utils.unfakeTimers(sandbox);
    sandbox.verifyAndRestore();
  });

  it('should record, replay, end', function() {
    // stub fs.exists, spawn, and port-alloc
    sandbox.stub(fs, 'exists', function(path, cb) {
      global.setTimeout(function() {
        cb(/wpr$/.test(path));
      }, 1);
    });
    var spawnStub = test_utils.stubOutProcessSpawn(sandbox);
    spawnStub.callback = function(proc, cmd, argv) {
      var stdout = '';
      if (/wpr$/.test(cmd) && 'record' === argv[0]) {
        stdout = '1.2.3.4\n';
      } else if (/wpr$/.test(cmd) && 'replay' === argv[0]) {
        stdout = '\t  1.2.3.4\r\n';
      } else if (/wpr$/.test(cmd) && 'getlog' === argv[0]) {
        stdout = 'gaga';
      }
      proc.stdout.emit('data', stdout);
      return false;
    };

    var wpr = new web_page_replay.WebPageReplay(app,
        {flags: {deviceAddr: '1.2.3.4'}, task: {}});
    wpr.scheduleRecord().then(function(ip) {
      should.equal('1.2.3.4', ip);
    });
    wpr.scheduleReplay().then(function(ip) {
      should.equal('1.2.3.4', ip);
    });
    wpr.scheduleGetErrorLog().then(function(errorLog) {
      should.equal('gaga', errorLog);
    });
    wpr.scheduleStop();
    test_utils.tickUntilIdle(app, sandbox);
    var cmd = /wpr$/;
    spawnStub.assertCalls(
        [cmd, 'status'],
        [cmd, 'record', '1.2.3.4'],
        [cmd, 'replay', '1.2.3.4'],
        [cmd, 'getlog', '1.2.3.4'],
        [cmd, 'stop', '1.2.3.4']
    );
  });
});