spec: get plugin and ember js specs running, remove cruft

fixes SD-1724

in previous refactorings, plugin and ember js specs stopped running, and
regular specs started running twice

test plan:
1. confirm that ember specs run and pass now (110 of them)
2. confirm that more regular specs run than before (cuz plugins)
3. confirm that the regular specs don't run twice (unless it does the
   retry thing)
4. `sudo -u clay test it every which way`

Change-Id: I24ac56b9d3082e25d15f06193c9a9e5c4313b7a7
Reviewed-on: https://gerrit.instructure.com/94305
Tested-by: Jenkins
Reviewed-by: Ryan Shaw <ryan@instructure.com>
Product-Review: Jon Jensen <jon@instructure.com>
QA-Review: Jon Jensen <jon@instructure.com>
This commit is contained in:
Jon Jensen 2016-11-02 17:22:23 -06:00
parent b0ef918241
commit 1c60698f56
7 changed files with 60 additions and 240 deletions

2
.gitignore vendored
View File

@ -52,8 +52,8 @@ npm-debug.log
/public/webpack-dist/
/spec/javascripts/webpack/
/spec/javascripts/compiled/
/spec/javascripts/load_tests.js
/spec/javascripts/requirejs_config.js
/spec/javascripts/runner.html
/spec/javascripts/tests.js
/tmp/
/vendor/bundle

View File

@ -1,2 +0,0 @@
test_page: spec/javascripts/runner.html

View File

@ -25,51 +25,23 @@ if (usingWebpack) {
{pattern: 'spec/javascripts/fixtures/*', included: false, served: true}
];
}else{
if (process.env.JS_SPEC_MATCHER) {
const files = glob.sync(process.env.JS_SPEC_MATCHER);
console.log('These spec files were matched:');
console.log(files);
karmaFiles = [
'spec/javascripts/requirejs_config.js',
'spec/javascripts/tests.js',
'public/javascripts/vendor/require.js',
'node_modules/karma-requirejs/lib/adapter.js',
'spec/javascripts/support/sinon/sinon-1.17.2.js',
'spec/javascripts/support/sinon/sinon-qunit-1.0.0.js',
'spec/javascripts/support/axe.js',
{pattern: 'public/javascripts/*.js', included: false, served: true},
{pattern: 'spec/javascripts/fixtures/*.html', included: false, served: true},
{pattern: 'spec/javascripts/tests.js', included: false, served: true},
{pattern: 'spec/javascripts/compiled/helpers/*.js', included: false, served: true}
];
files.forEach(f => karmaFiles.push({pattern: f, included: false, served: true}));
karmaFiles = karmaFiles.concat([
{pattern: 'spec/javascripts/fixtures/*', included: false, served: true},
{pattern: 'public/javascripts/**/*.js', included: false, served: true},
{pattern: 'public/dist/brandable_css/**/*.css', included: false, served: true},
'spec/javascripts/load_tests.js'
]);
} else {
karmaFiles = [
'spec/javascripts/requirejs_config.js',
'spec/javascripts/tests.js',
'public/javascripts/vendor/require.js',
'node_modules/karma-requirejs/lib/adapter.js',
'spec/javascripts/support/sinon/sinon-1.17.2.js',
'spec/javascripts/support/sinon/sinon-qunit-1.0.0.js',
'spec/javascripts/support/axe.js',
{pattern: 'public/javascripts/*.js', included: false, served: true},
{pattern: 'spec/javascripts/fixtures/*.html', included: false, served: true},
{pattern: 'spec/javascripts/tests.js', included: false, served: true},
{pattern: 'spec/javascripts/compiled/*.js', included: false, served: true},
{pattern: 'spec/javascripts/compiled/**/*.js', included: false, served: true},
{pattern: 'spec/**/javascripts/compiled/**/*.js', included: false, served: true},
{pattern: 'spec/javascripts/fixtures/*', included: false, served: true},
{pattern: 'public/javascripts/**/*.js', included: false, served: true},
{pattern: 'public/dist/brandable_css/**/*.css', included: false, served: true},
'spec/javascripts/load_tests.js'
]
}
karmaFiles = [
'spec/javascripts/requirejs_config.js',
'public/javascripts/vendor/require.js',
'node_modules/karma-requirejs/lib/adapter.js',
'spec/javascripts/support/sinon/sinon-1.17.2.js',
'spec/javascripts/support/sinon/sinon-qunit-1.0.0.js',
'spec/javascripts/support/axe.js',
{pattern: 'public/javascripts/*.js', included: false, served: true},
{pattern: 'spec/javascripts/fixtures/*.html', included: false, served: true},
{pattern: 'spec/javascripts/compiled/*.js', included: false, served: true},
{pattern: 'spec/javascripts/compiled/**/*.js', included: false, served: true},
{pattern: 'spec/**/javascripts/compiled/**/*.js', included: false, served: true},
{pattern: 'spec/javascripts/fixtures/*', included: false, served: true},
{pattern: 'public/javascripts/**/*.js', included: false, served: true},
{pattern: 'public/dist/brandable_css/**/*.css', included: false, served: true},
'spec/javascripts/load_tests.js'
]
}

View File

@ -3,7 +3,6 @@ require 'lib/canvas/require_js/client_app_extension'
module Canvas
module RequireJs
class << self
@@matcher = nil
def get_binding
binding
end
@ -11,14 +10,6 @@ module Canvas
PATH_REGEX = %r{.*?/javascripts/(plugins/)?(.*)\.js\z}
JS_ROOT = "#{Rails.root}/public/javascripts"
def matcher=(value)
@@matcher = value
end
def matcher
@@matcher || ENV['JS_SPEC_MATCHER'] || '**/*Spec.js'
end
# get all regular canvas (and plugin) bundles
def app_bundles
app_bundles = (

View File

@ -25,7 +25,7 @@ namespace :js do
"**/#{app_name}/**/*.spec.js"
end
desc 'generate QUnit runner file @ spec/javascripts/runner.html'
desc 'generate requirejs loader file @ spec/javascripts/load_tests.js'
task :generate_runner do
build_runner
end
@ -33,9 +33,9 @@ namespace :js do
def build_runner
require 'canvas/require_js'
require 'erubis'
output = Erubis::Eruby.new(File.read("#{Rails.root}/spec/javascripts/runner.html.erb")).
output = Erubis::Eruby.new(File.read("#{Rails.root}/spec/javascripts/load_tests.js.erb")).
result(Canvas::RequireJs.get_binding)
File.open("#{Rails.root}/spec/javascripts/runner.html", 'w') { |f| f.write(output) }
File.open("#{Rails.root}/spec/javascripts/load_tests.js", 'w') { |f| f.write(output) }
build_requirejs_config
end
@ -56,16 +56,6 @@ namespace :js do
output = Erubis::Eruby.new(File.read("#{Rails.root}/spec/javascripts/requirejs_config.js.erb")).
result(Canvas::RequireJs.get_binding)
File.open("#{Rails.root}/spec/javascripts/requirejs_config.js", 'w') { |f| f.write(output) }
matcher = Canvas::RequireJs.matcher
tests = Dir[
"public/javascripts/*[!bower]/#{matcher}",
"spec/javascripts/compiled/#{matcher}",
"spec/plugins/*/javascripts/compiled/#{matcher}"
].map{ |file| file.sub(/\.js$/, '').sub(/public\/javascripts\//, '') }
File.open("#{Rails.root}/spec/javascripts/tests.js", 'w') { |f|
f.write("window.__TESTS__ = #{JSON.pretty_generate(tests.shuffle(random: generate_prng))}")
}
end
desc 'test javascript specs with Karma'
@ -100,51 +90,48 @@ namespace :js do
d.match(/^\./) || ignored_embers.include?(d)
}.each do |ember_app|
puts "--> Running tests for '#{ember_app}' ember app"
Canvas::RequireJs.matcher = matcher_for_ember_app ember_app
ENV["JS_SPEC_MATCHER"] = matcher_for_ember_app ember_app
test_suite(reporter)
end
ENV['JS_SPEC_MATCHER'] = nil
end
# run test for non-ember apps
Canvas::RequireJs.matcher = nil
test_suite(reporter)
end
end
def test_suite(reporter=nil)
if test_js_with_timeout(300,reporter) != 0 && !ENV['JS_SPEC_MATCHER'] && ENV['retry'] != 'false'
puts "--> Karma tests failed." # retrying karma...
raise "Karma tests failed on second attempt." if test_js_with_timeout(400,reporter) != 0
end
def test_suite(reporter = nil)
return if test_js_with_timeout(300, reporter)
do_retry = ENV['retry'] != 'false' && !ENV['JS_SPEC_MATCHER']
raise "Karma tests failed" unless do_retry
puts "--> Karma tests failed." # retrying karma...
test_js_with_timeout(400, reporter) or raise "Karma tests failed on second attempt."
end
def test_js_with_timeout(timeout,reporter)
require 'canvas/require_js'
begin
Timeout::timeout(timeout) do
quick = ENV["quick"] && ENV["quick"] == "true"
unless quick
puts "--> do rake js:test quick=true to skip generating compiled coffeescript and handlebars."
Rake::Task['js:generate'].invoke
end
puts "--> executing browser tests with Karma"
build_runner
reporters = ['progress', 'coverage', reporter].reject(&:blank?).join(',')
command = %Q{./node_modules/karma/bin/karma start --browsers Chrome --single-run --reporters #{reporters}}
puts "running karma with command: #{command} on node #{`node -v`}"
system command
if $?.exitstatus != 0
puts 'some specs failed'
result = 1
else
result = 0
end
return result
Timeout::timeout(timeout) do
quick = ENV["quick"] && ENV["quick"] == "true"
unless quick
puts "--> do rake js:test quick=true to skip generating compiled coffeescript and handlebars."
Rake::Task['js:generate'].invoke
end
rescue Timeout::Error
puts "Karma tests reached timeout!"
puts "--> executing browser tests with Karma"
build_runner
reporters = ['progress', 'coverage', reporter].reject(&:blank?).join(',')
command = %Q{./node_modules/karma/bin/karma start --browsers Chrome --single-run --reporters #{reporters}}
puts "running karma with command: #{command} on node #{`node -v`}"
result = system(command)
puts 'some specs failed' unless result
result
end
rescue Timeout::Error
puts "Karma tests reached timeout!"
false
end
def coffee_destination(dir_or_file)

View File

@ -1,17 +1,15 @@
var thingsToLoadWithRequireJS = []
var TEST_REGEXP = /^\/base\/spec\/.*Spec\.js$/i
// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function (file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names so it works with our `baseUrl` below
// eg: converts '/base/spec/javascripts/fooSpec.js' to '../../spec/javascripts/fooSpec'
var normalizedTestModule = file
.replace(/^\/base\//, '../../')
.replace(/\.js$/, '')
thingsToLoadWithRequireJS.push(normalizedTestModule)
}
})
<%
matcher = ENV['JS_SPEC_MATCHER'] || 'spec/**/*Spec.js' # default to all regular canvas specs
files = Dir["spec/{javascripts,plugins/*/javascripts}/**/*{.spec,Spec}.js"] + # regular canvas (+ plugin) specs
Dir["public/javascripts/compiled/ember/**/*.spec.js"] # ember specs
files &= Dir[matcher]
files.each do |file|
file.sub!(/\A(spec|public\/javascripts)\//, {"spec/" => "../../spec/", "public/javascripts/" => ""})
file.sub!(/\.js\z/, '')
end
%>
var thingsToLoadWithRequireJS = <%= files.inspect %>
// include the english translations by default, same as would happen in
// production via common.js. this saves the test writer from having to stub

View File

@ -1,126 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv=Content-type content="text/html; charset=utf-8">
<title>Tests</title>
<link rel="stylesheet" href="support/qunit/qunit.css" type="text/css">
<style>
code {
font-size: 120%;
background-color: rgba(255, 255, 255, 0.75);
}
#fixture {
background: yellow;
padding: 10px;
margin: 10px 0;
border: solid 1px #ccc;
}
</style>
</head>
<body>
<h1 id="qunit-header">QUnit Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="fixtures"></div>
<script src="support/qunit/qunit.js"></script>
<script src="support/sinon/sinon-1.17.2.js"></script>
<script src="support/sinon/sinon-qunit-1.0.0.js"></script>
<script>
var require = {
urlArgs: "bust=" + (new Date()).getTime(),
baseUrl: '../../public/javascripts',
paths: <%= paths %>,
// non-amd shims
use: <%= shims %>,
packages: [
{
name: 'jqueryui',
location: 'vendor/jqueryui'
},
{
name: 'helpers',
location: '../../spec/javascripts/compiled/helpers',
main: 'helpers',
lib: './'
},
{
name: 'support',
location: '../../spec/javascripts/support',
main: 'support',
lib: './'
},
{
name: 'spec',
location: '../../spec'
},
].concat(<%= packages %>)
};
</script>
<script src="../../public/javascripts/vendor/require.js"></script>
<script>
// keep JSON.stingify from puking on dom nodes in testem
(function() {
var toString = Object.prototype.toString;
QUnit.log(function(result) {
if (result.actual instanceof HTMLElement) {
result.actual = result.actual.toString();
result.expected = result.expected.toString();
}
if (toString.call(result.actual) == '[object Array]') {
for (var i = 0; i < result.actual.length; i++) {
if (result.actual[i] instanceof HTMLElement) {
result.actual[i] = result.actual[i].toString();
result.expected[i] = result.expected[i].toString();
}
}
}
});
})();
// start loading specs now. if there's a callback by the time they finish
// loading, execute it.
var specsLoading = true;
var onSpecsLoaded = null;
require(<%=
Dir[
"public/javascripts/*[!bower]/#{matcher}",
"spec/javascripts/compiled/#{matcher}",
"spec/plugins/*/javascripts/compiled/#{matcher}"
].map{ |file| file.sub(/\.js$/, '').sub(/public\/javascripts\//, '') }.inspect
%>, function() {
specsLoading = false;
if (onSpecsLoaded) onSpecsLoaded();
});
// don't try and start right when QUnit.load finishes. we want to check
// spec loading status.
QUnit.config.autostart = false;
QUnit.begin(function() {
// callback executed at start of QUnit.load, but we need to let it finish
// first
setTimeout(function() {
// QUnit loaded and initialized. are the specs all loaded?
if (specsLoading) {
// if not, we need to wait for them before starting. fortunately, we
// have a nifty onSpecsLoaded callback just for that.
onSpecsLoaded = function() { QUnit.start(); };
} else {
// they are! get going
QUnit.start();
}
});
});
</script>
</body>
</html>