qunit-runner 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 371f9bd6512b7892f59bf25aa5f8373fde365d6a
4
+ data.tar.gz: a3ec017ff0fad9af6d3404e004b970cebe3b804a
5
+ SHA512:
6
+ metadata.gz: 10eece62b27f97caa3725d2dcc18b9a3103906b3987c52918ff4b5882abe2ee7c6f661b0c79fd104efbc14fcc0177290754b4e36564c7b6b48dfe6620e5960eb
7
+ data.tar.gz: 166c0de2e9e2ae1900cb5081ea955c938d834f22056231a668bf82167662c55ceee1448055c0d2a8a52c828f360df8d2dbf64863af6a63785a8d50dac14a7af0
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in qunit-runner.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 theScore Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # Qunit::Runner
2
+
3
+ A ruby command line runner for Qunit tests using PhantomJS
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'qunit-runner'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install qunit-runner
18
+
19
+ ## Usage
20
+
21
+ qunit-runner \[--timeout=milleseconds\] URL
22
+
23
+ This will run a test suite located at the provided URL, giving an appropriate
24
+ exit status and displaying test run progress and status.
25
+
26
+ ## API Usage
27
+
28
+ You can invoke the test runner from inside your application using the
29
+ `Qunit::Runner` class. Initialize the runner with the test URL, and then run the
30
+ engine, optionally specifying a timeout.
31
+
32
+ ```
33
+ url = "http://localhost:3000"
34
+ Qunit::Runner.new(url).run
35
+ ```
36
+
37
+ ## Contributing
38
+
39
+ 1. Fork it
40
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
41
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
42
+ 4. Push to the branch (`git push origin my-new-feature`)
43
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/qunit-runner ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'qunit/runner'
4
+ require 'thor'
5
+
6
+ class QunitRunnerCLI < Thor
7
+
8
+ desc "test URL", %{Run a qunit test suite at the specified URL}
9
+ option :timeout, :type => :numeric, :default => 10000,
10
+ :description => "Milliseconds to wait before giving up on the test suite"
11
+
12
+ def test(url)
13
+ Qunit::Runner.new(url).run(options[:timeout])
14
+ end
15
+
16
+ default_task :test
17
+ end
18
+
19
+ QunitRunnerCLI.start(ARGV)
@@ -0,0 +1,26 @@
1
+ module Qunit
2
+ class Logger
3
+ @print_color = !ENV.has_key?('DISABLE_COLOR')
4
+ class << self
5
+
6
+ def print(message, color = nil)
7
+ Kernel.print apply_color(message, color)
8
+ end
9
+
10
+ def puts(message, color = nil)
11
+ Kernel.puts apply_color(message, color)
12
+ end
13
+
14
+ protected
15
+
16
+ def apply_color(message, color = nil)
17
+ if !color.nil? && @print_color
18
+ message.send(color.to_sym)
19
+ else
20
+ message
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,163 @@
1
+ require 'qunit/logger'
2
+
3
+ module Qunit
4
+ class Parser
5
+
6
+ attr_reader :current_module
7
+ attr_reader :current_test
8
+ attr_reader :unfinished_modules
9
+ attr_reader :failed_assertions
10
+ attr_reader :total_failed
11
+ attr_reader :total_passed
12
+ attr_reader :total
13
+ attr_reader :duration
14
+ attr_reader :logger
15
+
16
+ def initialize
17
+ @logger = Qunit::Logger
18
+ @unfinished_modules = Hash.new
19
+ @failed_assertions = Array.new
20
+ @total_failed = 0
21
+ @total_passed = 0
22
+ @total = 0
23
+ @duration = 0
24
+ end
25
+
26
+ def parse(line)
27
+ params = JSON.parse line
28
+ event = params.shift
29
+ case event
30
+ when 'qunit.moduleStart'
31
+ module_start *params
32
+ when 'qunit.moduleDone'
33
+ module_done *params
34
+ when 'qunit.testStart'
35
+ test_start *params
36
+ when 'qunit.testDone'
37
+ test_done *params
38
+ when 'qunit.log'
39
+ qunit_log *params
40
+ when 'qunit.done'
41
+ qunit_done *params
42
+ when 'fail.load'
43
+ fail_load *params
44
+ when 'fail.timeout'
45
+ fail_timeout *params
46
+ when 'console'
47
+ console *params
48
+ end
49
+ end
50
+
51
+ def module_start(name)
52
+ name ||= "Unnamed Module"
53
+ @unfinished_modules[name.to_sym] = true
54
+ @current_module = name
55
+ # exit status
56
+ return false, nil
57
+ end
58
+
59
+ def module_done(name, *args)
60
+ name ||= "Unnamed Module"
61
+ @unfinished_modules.delete(name.to_sym)
62
+ # exit status
63
+ return false, nil
64
+ end
65
+
66
+ def test_start(name)
67
+ prefix = @current_module ? "#{@current_module} - " : ''
68
+ @current_test = "#{prefix}#{name}"
69
+ # exit status
70
+ return false, nil
71
+ end
72
+
73
+ def test_done(name, failed, *args)
74
+ if failed > 0
75
+ logger.print 'F', :red
76
+ else
77
+ logger.print '.'
78
+ end
79
+ # exit status
80
+ return false, nil
81
+ end
82
+
83
+ def qunit_log(result, actual, expected, message, source)
84
+ if not result
85
+ assertion = {
86
+ name: @current_test,
87
+ actual: actual,
88
+ expected: expected,
89
+ message: message,
90
+ source: source
91
+ }
92
+ @failed_assertions.push assertion
93
+ end
94
+ # exit status
95
+ return false, nil
96
+ end
97
+
98
+ def qunit_done(failed, passed, total, duration)
99
+ @total_failed += failed
100
+ @total_passed += passed
101
+ @total += total
102
+ @duration += duration
103
+ log_summary
104
+ end
105
+
106
+ def fail_load(url)
107
+ logger.puts "PhantomJS unable to load #{url} URI", :red
108
+ @total_failed += 1
109
+ @total += 1
110
+ log_summary
111
+ end
112
+
113
+ def fail_timeout
114
+ logger.puts "PhantomJS timed out.", :red
115
+ @total_failed += 1
116
+ @total += 1
117
+ log_summary
118
+ end
119
+
120
+ def console(message)
121
+ prefix = ''
122
+ if @current_test
123
+ prefix << "\n[%s]" % @current_test
124
+ elsif @current_module
125
+ prefix << "\n[%s]" % @current_module
126
+ end
127
+ prefix << ' CONSOLE: '
128
+ logger.print prefix, :magenta
129
+ logger.print message
130
+ logger.print "\n"
131
+ end
132
+
133
+ def log_summary
134
+ logger.puts ''
135
+ @failed_assertions.each do |assertion|
136
+ logger.puts assertion[:name]
137
+ logger.puts "Message: #{assertion[:message]}", :red
138
+ if assertion[:actual] != assertion[:expected]
139
+ logger.puts "Actual: #{assertion[:actual]}", :magenta
140
+ logger.puts "Expected: #{assertion[:expected]}", :yellow
141
+ end
142
+ if assertion[:source]
143
+ logger.puts assertion[:source], :cyan
144
+ end
145
+ logger.puts ''
146
+ end
147
+ if @total == 0
148
+ logger.puts "0/0 assertions ran (#{@duration/1000.0}s)", :magenta
149
+ else
150
+ logger.puts "#{@total_passed}/#{@total} assertions passed (#{@duration/1000.0}s)"
151
+ end
152
+ if @total_failed == 0 and @total > 0
153
+ logger.puts "OK", :green
154
+ # exit status
155
+ return true, 0
156
+ else
157
+ # exit status
158
+ return true, 1
159
+ end
160
+ end
161
+
162
+ end
163
+ end
@@ -0,0 +1,72 @@
1
+ require "qunit/runner/version"
2
+ require 'qunit/logger'
3
+ require 'qunit/parser'
4
+ require 'shellwords'
5
+ require 'open3'
6
+ require 'json'
7
+ require 'colorize'
8
+
9
+ module Qunit
10
+ class Runner
11
+ attr_reader :should_exit
12
+ attr_reader :exit_status
13
+ attr_reader :test_url
14
+ attr_reader :logger
15
+
16
+ def initialize(url)
17
+ $stdout.sync = true
18
+ @should_exit = false
19
+ @exit_status = 0
20
+ @test_url = url
21
+ @logger = Qunit::Logger
22
+ @parser = Qunit::Parser.new
23
+ end
24
+
25
+ def run(load_timeout = 10000)
26
+ root = File.dirname(File.dirname(__FILE__))
27
+ qunit_bridge = File.join root, 'vendor', 'js', 'qunit_bridge.js'
28
+ phantom_bridge = File.join root, 'vendor', 'js', 'phantom_bridge.js'
29
+ opts = {
30
+ timeout: load_timeout,
31
+ inject: qunit_bridge
32
+ }
33
+ cmd = Shellwords.join [
34
+ 'phantomjs',
35
+ phantom_bridge,
36
+ '/dev/stdout',
37
+ @test_url,
38
+ opts.to_json
39
+ ]
40
+ print_banner
41
+ Open3.popen3(cmd) do |i, o, e, t|
42
+ i.close
43
+ begin
44
+ while line = o.gets and !@should_exit
45
+ @should_exit, @exit_status = @parser.parse line
46
+ end
47
+ safe_kill t.pid
48
+ rescue Exception
49
+ safe_kill t.pid
50
+ raise
51
+ end
52
+ end
53
+ exit @exit_status
54
+ end
55
+
56
+ def safe_kill(pid)
57
+ begin
58
+ Process.kill("KILL", pid)
59
+ true
60
+ rescue
61
+ false
62
+ end
63
+ end
64
+
65
+ protected
66
+
67
+ def print_banner
68
+ logger.puts "Starting tests at url %s" % @test_url
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,6 @@
1
+ module Qunit
2
+ class Runner
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
6
+
@@ -0,0 +1,131 @@
1
+ /*global phantom:true*/
2
+ (function() {
3
+
4
+ 'use strict';
5
+
6
+ var fs = require('fs');
7
+
8
+ // The temporary file used for communications.
9
+ var tmpfile = phantom.args[0];
10
+ // The page .html file to load.
11
+ var url = phantom.args[1];
12
+ // Extra, optionally overridable stuff.
13
+ var options = JSON.parse(phantom.args[2] || "{}");
14
+
15
+ // Default options.
16
+ if (!options.timeout) { options.timeout = 5000; }
17
+
18
+ // Keep track of the last time a client message was sent.
19
+ var last = new Date();
20
+
21
+ // Messages are sent to the parent by appending them to the tempfile.
22
+ var sendMessage = function(arg) {
23
+ var args = Array.isArray(arg) ? arg : [].slice.call(arguments);
24
+ last = new Date();
25
+ fs.write(tmpfile, JSON.stringify(args) + '\n', 'a');
26
+ };
27
+
28
+ // This allows grunt to abort if the PhantomJS version isn't adequate.
29
+ sendMessage('private', 'version', phantom.version);
30
+
31
+ // Abort if the page doesn't send any messages for a while.
32
+ setInterval(function() {
33
+ if (new Date() - last > options.timeout) {
34
+ sendMessage('fail.timeout');
35
+ phantom.exit();
36
+ }
37
+ }, 100);
38
+
39
+ // Create a new page.
40
+ var page = require('webpage').create();
41
+
42
+ // Inject bridge script into client page.
43
+ var injected;
44
+ var inject = function() {
45
+ if (injected) { return; }
46
+ // Inject client-side helper script.
47
+ var scripts = Array.isArray(options.inject) ? options.inject : [options.inject];
48
+ sendMessage('inject', options.inject);
49
+ scripts.forEach(page.injectJs);
50
+ injected = true;
51
+ };
52
+
53
+ // Keep track if the client-side helper script already has been injected.
54
+ page.onUrlChanged = function(newUrl) {
55
+ injected = false;
56
+ sendMessage('onUrlChanged', newUrl);
57
+ };
58
+
59
+ // The client page must send its messages via alert(jsonstring).
60
+ page.onAlert = function(str) {
61
+ // The only thing that should ever alert "inject" is the custom event
62
+ // handler this script adds to be executed on DOMContentLoaded.
63
+ if (str === 'inject') {
64
+ inject();
65
+ return;
66
+ }
67
+ // Otherwise, parse the specified message string and send it back to grunt.
68
+ // Unless there's a parse error. Then, complain.
69
+ try {
70
+ sendMessage(JSON.parse(str));
71
+ } catch(err) {
72
+ sendMessage('error.invalidJSON', str);
73
+ }
74
+ };
75
+
76
+ // Relay console logging messages.
77
+ page.onConsoleMessage = function(message) {
78
+ if (!message.match(/^\[✓\].+/)) {
79
+ sendMessage('console', message);
80
+ }
81
+ };
82
+
83
+ // For debugging.
84
+ page.onResourceRequested = function(request) {
85
+ sendMessage('onResourceRequested', request);
86
+ };
87
+
88
+ page.onResourceReceived = function(request) {
89
+ if (request.stage === 'end') {
90
+ sendMessage('onResourceReceived', request);
91
+ }
92
+ };
93
+
94
+ page.onError = function(msg, trace) {
95
+ sendMessage('error.onError', msg, trace);
96
+ };
97
+
98
+ // Run before the page is loaded.
99
+ page.onInitialized = function() {
100
+ sendMessage('onInitialized');
101
+ // Abort if there is no bridge to inject.
102
+ if (!options.inject) { return; }
103
+ // Tell the client that when DOMContentLoaded fires, it needs to tell this
104
+ // script to inject the bridge. This should ensure that the bridge gets
105
+ // injected before any other DOMContentLoaded or window.load event handler.
106
+ page.evaluate(function() {
107
+ /*jshint browser:true, devel:true */
108
+ document.addEventListener('DOMContentLoaded', function() {
109
+ alert('inject');
110
+ }, false);
111
+ });
112
+ };
113
+
114
+ // Run when the page has finished loading.
115
+ page.onLoadFinished = function(status) {
116
+ // reset this handler to a no-op so further calls to onLoadFinished from iframes don't affect us
117
+ page.onLoadFinished = function() { /* no-op */}
118
+
119
+ // The window has loaded.
120
+ sendMessage('onLoadFinished', status);
121
+ if (status !== 'success') {
122
+ // File loading failure.
123
+ sendMessage('fail.load', url);
124
+ phantom.exit();
125
+ }
126
+ };
127
+
128
+ // Actually load url.
129
+ page.open(url);
130
+
131
+ }());
@@ -0,0 +1,59 @@
1
+ /*
2
+ * grunt-contrib-qunit
3
+ * http://gruntjs.com/
4
+ *
5
+ * Copyright (c) 2013 "Cowboy" Ben Alman, contributors
6
+ * Licensed under the MIT license.
7
+ */
8
+
9
+ /*global QUnit:true, alert:true*/
10
+ (function () {
11
+ 'use strict';
12
+
13
+ // Don't re-order tests.
14
+ QUnit.config.reorder = false;
15
+ // Run tests serially, not in parallel.
16
+ QUnit.config.autorun = false;
17
+
18
+ // Send messages to the parent PhantomJS process via alert! Good times!!
19
+ function sendMessage() {
20
+ var args = [].slice.call(arguments);
21
+ alert(JSON.stringify(args));
22
+ }
23
+
24
+ // These methods connect QUnit to PhantomJS.
25
+ QUnit.log(function(obj) {
26
+ // What is this I don’t even
27
+ if (obj.message === '[object Object], undefined:undefined') { return; }
28
+ // Parse some stuff before sending it.
29
+ var actual = QUnit.jsDump.parse(obj.actual);
30
+ var expected = QUnit.jsDump.parse(obj.expected);
31
+ // Send it.
32
+ sendMessage('qunit.log', obj.result, actual, expected, obj.message, obj.source);
33
+ });
34
+
35
+ QUnit.testStart(function(obj) {
36
+ sendMessage('qunit.testStart', obj.name);
37
+ });
38
+
39
+ QUnit.testDone(function(obj) {
40
+ sendMessage('qunit.testDone', obj.name, obj.failed, obj.passed, obj.total);
41
+ });
42
+
43
+ QUnit.moduleStart(function(obj) {
44
+ sendMessage('qunit.moduleStart', obj.name);
45
+ });
46
+
47
+ QUnit.moduleDone(function(obj) {
48
+ sendMessage('qunit.moduleDone', obj.name, obj.failed, obj.passed, obj.total);
49
+ });
50
+
51
+ QUnit.begin(function() {
52
+ sendMessage('qunit.begin');
53
+ });
54
+
55
+ QUnit.done(function(obj) {
56
+ sendMessage('qunit.done', obj.failed, obj.passed, obj.total, obj.runtime);
57
+ });
58
+ }());
59
+
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'qunit/runner/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "qunit-runner"
8
+ spec.version = Qunit::Runner::VERSION
9
+ spec.authors = ["M Smart, theScore Inc."]
10
+ spec.email = ["matthew.smart@thescore.com"]
11
+ spec.description = %q{QUnit test runner utizing phantomjs in ruby}
12
+ spec.summary = %q{QUnit test runner utizing phantomjs in ruby}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "pry"
24
+ spec.add_runtime_dependency "colorize"
25
+ spec.add_runtime_dependency "thor"
26
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qunit-runner
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - M Smart, theScore Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: colorize
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: QUnit test runner utizing phantomjs in ruby
84
+ email:
85
+ - matthew.smart@thescore.com
86
+ executables:
87
+ - qunit-runner
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - Gemfile
93
+ - LICENSE
94
+ - README.md
95
+ - Rakefile
96
+ - bin/qunit-runner
97
+ - lib/qunit/logger.rb
98
+ - lib/qunit/parser.rb
99
+ - lib/qunit/runner.rb
100
+ - lib/qunit/runner/version.rb
101
+ - lib/vendor/js/phantom_bridge.js
102
+ - lib/vendor/js/qunit_bridge.js
103
+ - qunit-runner.gemspec
104
+ homepage: ''
105
+ licenses:
106
+ - MIT
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 2.2.2
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: QUnit test runner utizing phantomjs in ruby
128
+ test_files: []