PhantomJS is abandoned, replace it with Selenium/Chrome headless

This commit is contained in:
Guillermo Iguaran 2017-10-19 11:01:52 -05:00
parent b7bf709823
commit 4dcf12a340
6 changed files with 31 additions and 151 deletions

View File

@ -14,6 +14,7 @@ services:
addons: addons:
postgresql: "9.6" postgresql: "9.6"
chrome: stable
apt: apt:
sources: sources:
- sourceline: "ppa:mc3man/trusty-media" - sourceline: "ppa:mc3man/trusty-media"
@ -34,7 +35,6 @@ before_install:
- "[[ $GEM != 'av:ujs' ]] || nvm install node" - "[[ $GEM != 'av:ujs' ]] || nvm install node"
- "[[ $GEM != 'av:ujs' ]] || node --version" - "[[ $GEM != 'av:ujs' ]] || node --version"
- "[[ $GEM != 'av:ujs' ]] || (cd actionview && npm install)" - "[[ $GEM != 'av:ujs' ]] || (cd actionview && npm install)"
- "[[ $GEM != 'av:ujs' ]] || [[ $(phantomjs --version) > '2' ]] || npm install -g phantomjs-prebuilt"
before_script: before_script:
# Set Sauce Labs username and access key. Obfuscated, purposefully not encrypted. # Set Sauce Labs username and access key. Obfuscated, purposefully not encrypted.

View File

@ -102,6 +102,11 @@ group :storage do
gem "mini_magick" gem "mini_magick"
end end
group :ujs do
gem "qunit-selenium"
gem "chromedriver-helper"
end
# Add your own local bundler stuff. # Add your own local bundler stuff.
local_gemfile = File.expand_path(".Gemfile", __dir__) local_gemfile = File.expand_path(".Gemfile", __dir__)
instance_eval File.read local_gemfile if File.exist? local_gemfile instance_eval File.read local_gemfile if File.exist? local_gemfile

View File

@ -136,6 +136,8 @@ GEM
addressable (2.5.1) addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2) public_suffix (~> 2.0, >= 2.0.2)
amq-protocol (2.2.0) amq-protocol (2.2.0)
archive-zip (0.7.0)
io-like (~> 0.3.0)
ast (2.3.0) ast (2.3.0)
aws-partitions (1.20.0) aws-partitions (1.20.0)
aws-sdk-core (3.3.0) aws-sdk-core (3.3.0)
@ -199,6 +201,9 @@ GEM
xpath (~> 2.0) xpath (~> 2.0)
childprocess (0.7.1) childprocess (0.7.1)
ffi (~> 1.0, >= 1.0.11) ffi (~> 1.0, >= 1.0.11)
chromedriver-helper (1.1.0)
archive-zip (~> 0.7.0)
nokogiri (~> 1.6)
coffee-rails (4.2.2) coffee-rails (4.2.2)
coffee-script (>= 2.2.0) coffee-script (>= 2.2.0)
railties (>= 4.0.0) railties (>= 4.0.0)
@ -289,6 +294,7 @@ GEM
http_parser.rb (0.6.0) http_parser.rb (0.6.0)
httpclient (2.8.3) httpclient (2.8.3)
i18n (0.8.6) i18n (0.8.6)
io-like (0.3.0)
jmespath (1.3.1) jmespath (1.3.1)
json (2.1.0) json (2.1.0)
jwt (1.5.6) jwt (1.5.6)
@ -356,6 +362,9 @@ GEM
public_suffix (2.0.5) public_suffix (2.0.5)
puma (3.9.1) puma (3.9.1)
que (0.14.0) que (0.14.0)
qunit-selenium (0.0.4)
selenium-webdriver
thor
racc (1.4.14) racc (1.4.14)
rack (2.0.3) rack (2.0.3)
rack-cache (1.7.0) rack-cache (1.7.0)
@ -498,6 +507,7 @@ DEPENDENCIES
bootsnap (>= 1.1.0) bootsnap (>= 1.1.0)
byebug byebug
capybara (~> 2.15) capybara (~> 2.15)
chromedriver-helper
coffee-rails coffee-rails
dalli (>= 2.2.1) dalli (>= 2.2.1)
delayed_job delayed_job
@ -520,6 +530,7 @@ DEPENDENCIES
puma puma
que que
queue_classic! queue_classic!
qunit-selenium
racc (>= 1.4.6) racc (>= 1.4.6)
rack-cache (~> 1.2) rack-cache (~> 1.2)
rails! rails!

View File

@ -45,7 +45,7 @@ namespace :test do
end end
end end
system("npm run lint && phantomjs ../ci/phantomjs.js http://localhost:4567/") system("npm run lint && bundle exec ruby ../ci/qunit-selenium-runner.rb http://localhost:4567/")
status = $?.to_i status = $?.to_i
ensure ensure
Process.kill("KILL", pid) if pid Process.kill("KILL", pid) if pid

View File

@ -1,149 +0,0 @@
/*
* PhantomJS Runner QUnit Plugin 1.2.0
*
* PhantomJS binaries: http://phantomjs.org/download.html
* Requires PhantomJS 1.6+ (1.7+ recommended)
*
* Run with:
* phantomjs runner.js [url-of-your-qunit-testsuite]
*
* e.g.
* phantomjs runner.js http://localhost/qunit/test/index.html
*/
/*global phantom:false, require:false, console:false, window:false, QUnit:false */
(function() {
'use strict';
var url, page, timeout,
args = require('system').args;
// arg[0]: scriptName, args[1...]: arguments
if (args.length < 2 || args.length > 3) {
console.error('Usage:\n phantomjs runner.js [url-of-your-qunit-testsuite] [timeout-in-seconds]');
phantom.exit(1);
}
url = args[1];
page = require('webpage').create();
if (args[2] !== undefined) {
timeout = parseInt(args[2], 10);
}
// Route `console.log()` calls from within the Page context to the main Phantom context (i.e. current `this`)
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.onInitialized = function() {
page.evaluate(addLogging);
};
page.onCallback = function(message) {
var result,
failed;
if (message) {
if (message.name === 'QUnit.done') {
result = message.data;
failed = !result || !result.total || result.failed;
if (!result.total) {
console.error('No tests were executed. Are you loading tests asynchronously?');
}
phantom.exit(failed ? 1 : 0);
}
}
};
page.open(url, function(status) {
if (status !== 'success') {
console.error('Unable to access network: ' + status);
phantom.exit(1);
} else {
// Cannot do this verification with the 'DOMContentLoaded' handler because it
// will be too late to attach it if a page does not have any script tags.
var qunitMissing = page.evaluate(function() { return (typeof QUnit === 'undefined' || !QUnit); });
if (qunitMissing) {
console.error('The `QUnit` object is not present on this page.');
phantom.exit(1);
}
// Set a timeout on the test running, otherwise tests with async problems will hang forever
if (typeof timeout === 'number') {
setTimeout(function() {
console.error('The specified timeout of ' + timeout + ' seconds has expired. Aborting...');
phantom.exit(1);
}, timeout * 1000);
}
// Do nothing... the callback mechanism will handle everything!
}
});
function addLogging() {
window.document.addEventListener('DOMContentLoaded', function() {
var currentTestAssertions = [];
QUnit.log(function(details) {
var response;
// Ignore passing assertions
if (details.result) {
return;
}
response = details.message || '';
if (typeof details.expected !== 'undefined') {
if (response) {
response += ', ';
}
response += 'expected: ' + details.expected + ', but was: ' + details.actual;
}
if (details.source) {
response += "\n" + details.source;
}
currentTestAssertions.push('Failed assertion: ' + response);
});
QUnit.testDone(function(result) {
var i,
len,
name = '';
if (result.module) {
name += result.module + ': ';
}
name += result.name;
if (result.failed) {
console.log('\n' + 'Test failed: ' + name);
for (i = 0, len = currentTestAssertions.length; i < len; i++) {
console.log(' ' + currentTestAssertions[i]);
}
}
currentTestAssertions.length = 0;
});
QUnit.done(function(result) {
console.log('\n' + 'Took ' + result.runtime + 'ms to run ' + result.total + ' tests. ' + result.passed + ' passed, ' + result.failed + ' failed.');
if (typeof window.callPhantom === 'function') {
window.callPhantom({
'name': 'QUnit.done',
'data': result
});
}
});
}, false);
}
})();

View File

@ -0,0 +1,13 @@
require 'qunit/selenium/test_runner'
require 'chromedriver/helper'
driver_options = Selenium::WebDriver::Chrome::Options.new
driver_options.add_argument('--headless')
driver_options.add_argument('--disable-gpu')
driver = ::Selenium::WebDriver.for(:chrome, options: driver_options)
result = QUnit::Selenium::TestRunner.new(driver).open(ARGV[0], timeout: 60)
driver.quit
puts "Time: #{result.duration} seconds, Total: #{result.tests[:total]}, Passed: #{result.tests[:passed]}, Failed: #{result.tests[:failed]}"
exit(result.tests[:failed] > 0 ? 1 : 0)