├── VERSION ├── .gitignore ├── .document ├── lib ├── watchr_script ├── jstdutil │ ├── colorful_html.rb │ ├── hooks.rb │ ├── test_file.rb │ ├── redgreen.rb │ ├── cli.rb │ ├── formatter.rb │ ├── autotest.rb │ ├── jstestdriver │ │ ├── config.rb │ │ └── server.rb │ └── test_runner.rb └── jstdutil.rb ├── mantest.rb ├── bin ├── jsautotest └── jstestdriver ├── TODO.org ├── test ├── redgreen_test.rb ├── jstestdriver_test.rb ├── colorful_html_test.rb ├── jstdutil_test.rb ├── jstestdriver_config_test.rb ├── test_helper.rb ├── cli_test.rb ├── test_file_test.rb └── formatter_test.rb ├── README.rdoc ├── LICENSE ├── Rakefile └── jstdutil.gemspec /VERSION: -------------------------------------------------------------------------------- 1 | 0.1.1 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw? 2 | .DS_Store 3 | coverage 4 | rdoc 5 | pkg 6 | -------------------------------------------------------------------------------- /.document: -------------------------------------------------------------------------------- 1 | README.rdoc 2 | lib/**/*.rb 3 | bin/* 4 | features/**/*.feature 5 | LICENSE 6 | -------------------------------------------------------------------------------- /lib/watchr_script: -------------------------------------------------------------------------------- 1 | watch('(.*\.js)') do |match_data| 2 | runner = $jstestdriver_test_runner 3 | runner.run(runner.test_cases(match_data)) 4 | end 5 | -------------------------------------------------------------------------------- /mantest.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift("/home/christian/projects/jstdutil/lib/") 2 | require "jstdutil" 3 | require "jstdutil/test_runner" 4 | 5 | runner = Jstdutil::TestRunner.new 6 | runner.run 7 | 8 | at_exit do 9 | "Exiting" 10 | end 11 | -------------------------------------------------------------------------------- /bin/jsautotest: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "jstdutil" 3 | require "jstdutil/autotest" 4 | 5 | begin 6 | Jstdutil::Autotest.new($*).run 7 | rescue StandardError => err 8 | puts "An error occurred" 9 | puts err.message 10 | end 11 | -------------------------------------------------------------------------------- /bin/jstestdriver: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | require "jstdutil" 4 | require "jstdutil/cli" 5 | rescue LoadError => err 6 | exit 7 | end 8 | 9 | begin 10 | $stdout.puts Jstdutil::Cli.run($*) 11 | rescue StandardError => err 12 | # Swallow... 13 | end 14 | -------------------------------------------------------------------------------- /TODO.org: -------------------------------------------------------------------------------- 1 | #+SEQ_TODO: TODO INPR DONE 2 | 3 | * TODO Catch exceptions and quit cleanly 4 | * TODO Print results from jstestdriver in real-time from jsautotest 5 | * TODO Don't stop the server if the current instance didn't start it 6 | * TODO Add some tests to autotest and test runner 7 | * TODO Catch errors caused by JsTestDriver picking up temp files such as #file.js# 8 | -------------------------------------------------------------------------------- /lib/jstdutil/colorful_html.rb: -------------------------------------------------------------------------------- 1 | module Jstdutil 2 | class ColorfulHtml 3 | 4 | module Color 5 | 6 | def self.method_missing(color_name, *args) 7 | color(color_name) + args.first + "" 8 | end 9 | 10 | def self.color(color) 11 | "" 12 | end 13 | end 14 | 15 | def self.wrap_report(report) 16 | "
#{report}
" 17 | end 18 | 19 | end 20 | end -------------------------------------------------------------------------------- /test/redgreen_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class RedGreenTest < Test::Unit::TestCase 4 | context "adding pretty colors" do 5 | 6 | should "wrap in green" do 7 | assert_equal "\e[32mtrees\e[0m", Jstdutil::RedGreen::Color.green("trees") 8 | end 9 | 10 | should "wrap in red" do 11 | assert_equal "\e[31mdress\e[0m", Jstdutil::RedGreen::Color.red("dress") 12 | end 13 | 14 | end 15 | 16 | context "wrapping report" do 17 | 18 | should "add nothing" do 19 | assert_equal "bare", Jstdutil::RedGreen.wrap_report("bare") 20 | end 21 | 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /README.rdoc: -------------------------------------------------------------------------------- 1 | = jstdutil 2 | 3 | Description goes here. 4 | 5 | == Note on Patches/Merge Requests 6 | 7 | * Fork the project. 8 | * Make your feature addition or bug fix. 9 | * Add tests for it. This is important so I don't break it in a 10 | future version unintentionally. 11 | * Commit, do not mess with rakefile, version, or history. 12 | (if you want to have your own version, that is fine but 13 | bump version in a commit by itself I can ignore when I pull) 14 | * Send me a merge request. Bonus points for topic branches. 15 | 16 | == Copyright 17 | 18 | Copyright (c) 2009 Christian Johansen. See LICENSE for details. 19 | -------------------------------------------------------------------------------- /test/jstestdriver_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class JstdutilCliTest < Test::Unit::TestCase 4 | def setup 5 | @bin = File.join(File.dirname(__FILE__), "..", "bin", "jstestdriver") 6 | end 7 | 8 | context "running the binary" do 9 | should "report success to $stdout" do 10 | jar = "JsTestDriver.jar" 11 | stdout = nil 12 | 13 | capture_stderr do 14 | stdout = capture_stdout do 15 | with_jars(jar) do |dir| 16 | `ruby -Ilib #@bin --jar #{File.join(dir, jar)}` 17 | end 18 | end 19 | end 20 | 21 | assert_equal "\n", stdout 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /test/colorful_html_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class ColorfulHtmlTest < Test::Unit::TestCase 4 | context "adding pretty colors" do 5 | 6 | should "wrap in green" do 7 | assert_equal "trees", Jstdutil::ColorfulHtml::Color.green("trees") 8 | end 9 | 10 | should "wrap in red" do 11 | assert_equal "dress", Jstdutil::ColorfulHtml::Color.red("dress") 12 | end 13 | 14 | end 15 | 16 | context "wrapping report" do 17 | 18 | should "add styles and pre" do 19 | assert_equal "
present
", 20 | Jstdutil::ColorfulHtml.wrap_report("present") 21 | end 22 | 23 | end 24 | 25 | end 26 | -------------------------------------------------------------------------------- /lib/jstdutil/hooks.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Observer module/hooks module, modeled exactly like 3 | # ZenTest::Autotest, in order to ease porting of addons like autotest-screen 4 | # 5 | # In order to use the hooks module, the including class needs to define an 6 | # AVAILABLE_HOOKS constant hash. The rest is handled by the mixin module. 7 | # 8 | module Hooks 9 | def self.included(target) 10 | target.class_eval do 11 | @@hooks = {} 12 | target::AVAILABLE_HOOKS.each { |hook| @@hooks[hook] = [] } 13 | 14 | def self.add_hook(hook, &block) 15 | @@hooks[hook] << block 16 | end 17 | 18 | def self.hook(hook, *args) 19 | @@hooks[hook].any? do |plugin| 20 | plugin[self, *args] 21 | end 22 | end 23 | 24 | def hook(hook) 25 | self.class.hook(hook) 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/jstdutil/test_file.rb: -------------------------------------------------------------------------------- 1 | require "rake" 2 | 3 | module Jstdutil 4 | # Knows how to map source files to test files, how to extract test cases 5 | # and so on. 6 | # 7 | class TestFile 8 | def initialize(file) 9 | @file = file 10 | end 11 | 12 | def test_files 13 | return @test_files if @test_files 14 | 15 | if @file =~ /(_test[^\/]+)|([^\/]+_test)\.js/ 16 | @test_files = [@file] 17 | else 18 | name = File.basename(@file).gsub(/(_test)|(test_)|(\.js)/, "") 19 | @test_files = FileList["**/#{name}_test.js", "**/test_#{name}.js"].uniq 20 | end 21 | end 22 | 23 | def test_cases 24 | return @cases if @cases 25 | 26 | @cases = test_files.collect do |file| 27 | File.read(file).scan(/TestCase\(["']([^"']*)/) 28 | end 29 | 30 | @cases.flatten! 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/jstdutil/redgreen.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require 'Win32/Console/ANSI' if PLATFORM =~ /win32/ 3 | rescue LoadError 4 | raise 'You must gem install win32console to use color on Windows' 5 | rescue NameError 6 | # PLATFORM is not defined, not a problem on windows. 7 | # On other platforms we don't care 8 | end 9 | module Jstdutil 10 | class RedGreen 11 | # Borrowed from the ruby redgreen gem 12 | # Not included as a gem dependency since it drags in Test::Unit 13 | # and friends, which is overkill for our situation 14 | module Color 15 | COLORS = { :clear => 0, :red => 31, :green => 32, :yellow => 33 } 16 | 17 | def self.method_missing(color_name, *args) 18 | color(color_name) + args.first + color(:clear) 19 | end 20 | 21 | def self.color(color) 22 | "\e[#{COLORS[color.to_sym]}m" 23 | end 24 | end 25 | 26 | def self.wrap_report(report) 27 | report 28 | end 29 | 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /test/jstdutil_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class JstdutilTest < Test::Unit::TestCase 4 | context "locating jar file" do 5 | setup do 6 | @newest = "jstestdriver-1.1.jar" 7 | @jars = ["JsTestDriver-1.0b.jar", "jstestdriver-1.0.jar", @newest] 8 | end 9 | 10 | should "use most recent test driver" do 11 | with_jars(@jars) do |dir| 12 | assert_equal @newest, File.basename(Jstdutil.jar(dir)) 13 | end 14 | end 15 | 16 | should "use $JSTESTDRIVER_HOME if no classpath is given" do 17 | with_jars(@jars) do |dir| 18 | with_env("JSTESTDRIVER_HOME", dir) do 19 | assert_equal @newest, File.basename(Jstdutil.jar) 20 | end 21 | end 22 | end 23 | 24 | should "raise exception if no classpath is provided, and env not set" do 25 | with_env("JSTESTDRIVER_HOME", nil) do 26 | assert_raise FileNotFoundError do 27 | Jstdutil.jar 28 | end 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/jstdutil/cli.rb: -------------------------------------------------------------------------------- 1 | module Jstdutil 2 | # 3 | # Jstdutil::Cli is a tiny wrapper to the JsTestDriver 4 | # jar, simply allowing you to avoid the clunkiness of `java -jar FILE [ARGS]` 5 | # 6 | # The wrapper also formats output with JsRedGreen, yielding 7 | # beautiful test reports. 8 | # 9 | # In addition to the JsTestDriver arguments you can specify the path 10 | # to the jar file by --jar. This kinda defeats the purpose, though, 11 | # so a better solution is to set the environment variable 12 | # $JSTESTDRIVER_HOME to where the jar file lives (see JsTestDriver.jar). 13 | # 14 | class Cli 15 | def self.run(args = []) 16 | args = args.join(" ") 17 | jar = (args.match(/--jar\s+([^\s]+)/) || [])[1] || Jstdutil.jar 18 | format_type = args.match(/--html/) ? Jstdutil::ColorfulHtml : Jstdutil::RedGreen; 19 | report = Jstdutil.run("#{args.gsub(/(--jar\s+[^\s]+|--html)/, '')}", jar) 20 | Jstdutil::Formatter.format(report, format_type) 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/jstdutil/formatter.rb: -------------------------------------------------------------------------------- 1 | module Jstdutil 2 | class Formatter 3 | # 4 | # Process report from JsTestDriver and colorize it with beautiful 5 | # colors. Returns report with encoded colors. 6 | # 7 | def self.format(report, type) 8 | return "" if report.nil? 9 | 10 | type.wrap_report(report.split("\n").collect do |line| 11 | if line =~ /Passed: 0; Fails: 0; Errors:? 0/ 12 | type::Color.yellow(line) 13 | elsif line =~ /Passed: \d+; Fails: (\d+); Errors:? (\d+)/ 14 | type::Color.send($1.to_i + $2.to_i != 0 ? :red : :green, line) 15 | elsif line =~ /^[\.EF]+$/ 16 | line.gsub(/\./, type::Color.green(".")).gsub(/F/, type::Color.red("F")).gsub("E", type::Color.yellow("E")) 17 | elsif line =~ /failed/ 18 | type::Color.red(line) 19 | elsif line =~ /passed/ 20 | type::Color.green(line) 21 | elsif line =~ /error/ 22 | type::Color.yellow(line) 23 | else 24 | line 25 | end 26 | end.join("\n")) 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Christian Johansen 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /lib/jstdutil.rb: -------------------------------------------------------------------------------- 1 | require "jstdutil/formatter" 2 | require "jstdutil/redgreen" 3 | require "jstdutil/colorful_html" 4 | #require "jstdutil/autotest" 5 | 6 | module Jstdutil 7 | def self.install_dir 8 | File.expand_path(File.dirname(__FILE__)) 9 | end 10 | 11 | # 12 | # Locate Jar file from a given path. Default classpath is $JSTDUTIL_HOME 13 | # Finds and returns the first file matching jstest*.jar (case insensitive). 14 | # Also checks current working directory 15 | # 16 | def self.jar(classpath = ENV["JSTESTDRIVER_HOME"] || Dir.pwd) 17 | files = Dir.glob(File.join(classpath, 'jstest*.jar'), File::FNM_CASEFOLD) 18 | files.sort! { |f1, f2| f1.downcase <=> f2.downcase } 19 | 20 | if !files || !files.first 21 | msg = "Unable to load jar file from #{classpath}\n" << 22 | "Check that $JSTESTDRIVER_HOME is set correctly" 23 | raise FileNotFoundError.new(msg) 24 | end 25 | 26 | files[-1] 27 | end 28 | 29 | # 30 | # Run the jar through the java command 31 | # 32 | def self.run(args, jar) 33 | begin 34 | `java -jar #{jar} #{args}` 35 | rescue Exception 36 | end 37 | end 38 | end 39 | 40 | class FileNotFoundError < StandardError 41 | end 42 | -------------------------------------------------------------------------------- /test/jstestdriver_config_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | require "jstdutil/jstestdriver/config" 3 | 4 | class JsTestDriverConfigTest < Test::Unit::TestCase 5 | context "creating JsTestDriverConfig instances" do 6 | setup do 7 | @file = "__jstd.conf" 8 | @server = "http://localhost:4242" 9 | File.open(@file, "w") { |f| f.puts "server: #{@server}" } 10 | end 11 | 12 | teardown do 13 | File.delete(@file) if File.exists?(@file) 14 | end 15 | 16 | should "work from existing file" do 17 | config = nil 18 | 19 | assert_nothing_raised do 20 | config = Jstdutil::JsTestDriver::Config.new @file 21 | end 22 | 23 | assert_equal @server, config.server 24 | end 25 | 26 | should "work from string config" do 27 | config = nil 28 | 29 | assert_nothing_raised do 30 | config = Jstdutil::JsTestDriver::Config.new "server: #{@server}" 31 | end 32 | 33 | assert_equal @server, config.server 34 | end 35 | 36 | should "raise error if no valid configuration is provided" do 37 | assert_raise ArgumentError do 38 | Jstdutil::JsTestDriver::Config.new "bogus" 39 | end 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/jstdutil/autotest.rb: -------------------------------------------------------------------------------- 1 | require "jstdutil/test_runner" 2 | require "jstdutil/hooks" 3 | require "watchr" 4 | 5 | module Jstdutil 6 | class Autotest 7 | attr_reader :runner 8 | AVAILABLE_HOOKS = [:initialize, :died, :quit, :ran_command, :run_command, :waiting] 9 | include Hooks 10 | 11 | def initialize(args) 12 | absolute_path = Pathname(File.join(Jstdutil.install_dir, "watchr_script")) 13 | script = Watchr::Script.new(absolute_path) 14 | @watchr_controller = Watchr::Controller.new(script, Watchr.handler.new) 15 | @runner = Jstdutil::TestRunner.new(args) 16 | $jstestdriver_test_runner = @runner 17 | @interrupted_at = nil 18 | rescue StandardError => err 19 | raise err 20 | end 21 | 22 | def run 23 | hook(:initialize) 24 | 25 | trap("INT") do 26 | if @interrupted_at && Time.now - @interrupted_at < 2 27 | puts "No more testing today, shutting down" 28 | @runner.finalize 29 | exit 30 | else 31 | @interrupted_at = Time.now 32 | puts "Running all tests, hit Ctrl-c again to exit" 33 | @runner.run 34 | end 35 | end 36 | 37 | @runner.run 38 | @watchr_controller.run 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'test/unit' 3 | require 'shoulda' 4 | require 'mocha' 5 | require 'fileutils' 6 | require 'redgreen' if RUBY_VERSION < "1.9" 7 | 8 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) 9 | $LOAD_PATH.unshift(File.dirname(__FILE__)) 10 | require 'jstdutil' 11 | 12 | class Test::Unit::TestCase 13 | def capture_stdout 14 | ios = StringIO.new 15 | stdout = $stdout 16 | $stdout = ios 17 | 18 | begin 19 | yield 20 | ensure 21 | $stdout = stdout 22 | ios 23 | end 24 | end 25 | 26 | def capture_stderr 27 | ios = StringIO.new 28 | stderr = $stderr 29 | $stderr = ios 30 | 31 | begin 32 | yield 33 | ensure 34 | $stderr = stderr 35 | ios 36 | end 37 | end 38 | 39 | def with_jars(jars = "JsTestDriver-1.0b.jar", dir = "data") 40 | FileUtils.rm_rf(dir) 41 | Dir.mkdir(dir) 42 | 43 | [jars].flatten.each do |lib| 44 | File.open(File.join(dir, lib), "w") { |f| f.puts "" } 45 | end 46 | 47 | begin 48 | yield dir 49 | ensure 50 | FileUtils.rm_rf(dir) 51 | end 52 | end 53 | 54 | def with_env(name, value) 55 | env = ENV[name] 56 | ENV[name] = value 57 | 58 | begin 59 | yield 60 | ensure 61 | ENV[name] = value 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/jstdutil/jstestdriver/config.rb: -------------------------------------------------------------------------------- 1 | module Jstdutil 2 | module JsTestDriver 3 | # Simple interface to JsTestDriver configuration 4 | # Can instantiate with either a configuration file or string contents 5 | # 6 | # config = Jstdutil::JsTestDriverConfig.new "jsTestDriver.conf" 7 | # config.server #=> "http://localhost:4224" 8 | # 9 | class Config 10 | def initialize(file) 11 | begin 12 | load_config(File.read(file)) 13 | rescue 14 | load_config(file) 15 | rescue 16 | msg = "Configuration must be an existing file or valid JsTestDriver " << 17 | "configuration string (contain atleast server)" 18 | raise ArgumentError.new(msg) 19 | end 20 | end 21 | 22 | def method_missing(name, *args, &block) 23 | return @contents[name.to_s] if @contents.key?(name.to_s) 24 | super 25 | end 26 | 27 | def respond_to?(name) 28 | return true if @contents.key?(name.to_s) 29 | super 30 | end 31 | 32 | private 33 | def load_config(contents) 34 | @contents = YAML.load(contents) 35 | 36 | if !@contents.respond_to?(:key?) || !@contents.key?("server") 37 | raise ArgumentError.new("Error: Unable to locate 'server' configuration setting. Did you provide a --config?") 38 | end 39 | 40 | @contents 41 | end 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/cli_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | require "jstdutil/cli" 3 | require "fileutils" 4 | 5 | class JstdutilCliTest < Test::Unit::TestCase 6 | context "running the cli" do 7 | should "run jstestdriver command through JsRedGreen with given jar" do 8 | jar = "path/to.jar" 9 | result = "REPORT" 10 | Jstdutil.expects(:run).with("--tests all ", jar).returns(result) 11 | Jstdutil::Formatter.expects(:format).with(result, Jstdutil::RedGreen).returns(result * 2) 12 | 13 | assert_equal result * 2, Jstdutil::Cli.run("--tests all --jar #{jar}".split(" ")) 14 | end 15 | 16 | should "run jstestdriver command through JsRedGreen with jar from env" do 17 | jar = "path/to.jar" 18 | result = "REPORT" 19 | Jstdutil.expects(:jar).returns(jar) 20 | Jstdutil.expects(:run).with("--tests all", jar).returns(result) 21 | Jstdutil::Formatter.expects(:format).with(result, Jstdutil::RedGreen).returns(result * 2) 22 | 23 | assert_equal result * 2, Jstdutil::Cli.run("--tests all".split(" ")) 24 | end 25 | 26 | should "run jstestdriver command through JsColorfulHtml with --html" do 27 | jar = "path/to.jar" 28 | result = "REPORT" 29 | Jstdutil.expects(:jar).returns(jar) 30 | Jstdutil.expects(:run).with("--tests all ", jar).returns(result) 31 | Jstdutil::Formatter.expects(:format).with(result, Jstdutil::ColorfulHtml).returns(result * 2) 32 | 33 | assert_equal result * 2, Jstdutil::Cli.run("--tests all --html".split(" ")) 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /test/test_file_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | require "jstdutil/test_file" 3 | require "fileutils" 4 | 5 | class TestFileTest < Test::Unit::TestCase 6 | context "test files" do 7 | should "be file itself if name is like _test.js" do 8 | file = "some_test.js" 9 | test_file = Jstdutil::TestFile.new(file) 10 | 11 | assert_equal [file], test_file.test_files 12 | end 13 | 14 | should "find files like _test.js" do 15 | file = "some.js" 16 | test_file = Jstdutil::TestFile.new(file) 17 | FileList.expects(:new).with("**/some_test.js", "**/test_some.js").returns([]) 18 | 19 | assert test_file.test_files 20 | end 21 | end 22 | 23 | context "test cases" do 24 | setup do 25 | @dir = "__testdata" 26 | @files = ["src/some.js", "test/some_test.js", "test/other_test.js"] 27 | @cases = ["SomeTest", "OtherTest", "YetAnotherTest"] 28 | @contents = { @files[1] => 'new TestCase("' + @cases[0] + '", {});', 29 | @files[2] => "new TestCase('#{@cases[1]}', {});\nnew TestCase('#{@cases[2]}', {});" } 30 | 31 | @files.each do |file| 32 | content = @contents[file] || "" 33 | file = File.join(@dir, file) 34 | FileUtils.mkdir_p(File.dirname(file)) 35 | File.open(file, "w") { |f| f.puts(content) } 36 | end 37 | end 38 | 39 | teardown do 40 | FileUtils.rm_rf(@dir) 41 | end 42 | 43 | should "find test case in file" do 44 | test_file = Jstdutil::TestFile.new(@files[0]) 45 | 46 | assert_equal @cases[0..0], test_file.test_cases 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /test/formatter_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class FormatterTest < Test::Unit::TestCase 4 | context "formatting report" do 5 | setup do 6 | @report = <<-REPORT 7 | .FE 8 | Total 3 tests (Passed: 1; Fails: 1; Errors: 1) (2.00 ms) 9 | Mozilla 1.9.1.2: Run 3 tests (Passed: 1; Fails: 1; Errors 1) (2.00 ms) 10 | GreeterTest.testSomethingElse failed (1.00 ms): expected "1" but was "2" 11 | ()@http://localhost:4224/test/test/greeter_test.js:10 12 | [LOG] UH! 13 | GreeterTest.testSomethingElseFails error (1.00 ms): assertEqual is not defined 14 | ()@http://localhost:4224/test/test/greeter_test.js:14 15 | REPORT 16 | end 17 | 18 | should "add pretty colors for both RedGreen and ColorfulHtml" do 19 | verify_pretty_colors(Jstdutil::RedGreen) 20 | verify_pretty_colors(Jstdutil::ColorfulHtml) 21 | end 22 | 23 | end 24 | 25 | def verify_pretty_colors(type) 26 | report = Jstdutil::Formatter.format(@report, type) 27 | 28 | lines = @report.split("\n") 29 | 30 | expected = type::Color.green(".") + 31 | type::Color.red("F") + 32 | type::Color.yellow("E") + "\n" 33 | expected << type::Color.red(lines[1]) + "\n" 34 | expected << type::Color.red(lines[2]) + "\n" 35 | expected << type::Color.red(lines[3]) + "\n" 36 | expected << lines[4] + "\n" 37 | expected << lines[5] + "\n" 38 | expected << type::Color.yellow(lines[6]) + "\n" 39 | expected << lines[7] 40 | 41 | expected = type.wrap_report(expected) 42 | 43 | expected.split("\n").size.times {|i| 44 | assert_equal expected.split("\n")[i], report.split("\n")[i] 45 | } 46 | assert_equal expected, report 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/jstdutil/jstestdriver/server.rb: -------------------------------------------------------------------------------- 1 | # require 'open3' 2 | require "uri" 3 | 4 | module Jstdutil 5 | module JsTestDriver 6 | class Server 7 | attr_reader :uri 8 | 9 | def initialize(config, args = nil) 10 | uri = config.respond_to?(:server) ? config.server : config 11 | @uri = URI.parse(uri) 12 | @args = args 13 | @pid = nil 14 | rescue URI::InvalidURIError => err 15 | raise StandardError.new("Invalid test driver server URL #{uri}") 16 | end 17 | 18 | def running? 19 | response = nil 20 | 21 | begin 22 | Net::HTTP.start(@uri.host, @uri.port) { |http| response = http.head("/") } 23 | rescue Errno::ECONNREFUSED => err 24 | return false 25 | end 26 | 27 | response.code == "200" 28 | end 29 | 30 | def start 31 | if !["localhost", "127.0.0.1", "0.0.0.0"].include?(@uri.host) 32 | raise "Unable to start remote server on #{@uri.host}" 33 | end 34 | 35 | puts "Starting server on http://#{@uri.host}:#{@uri.port}" 36 | # @server = IO.popen("jstestdriver #{@args} --port #{@uri.port}") 37 | # [stdin, stdout, stderr] = Open3.popen3("jstestdriver #{@args} --port #{@uri.port}") 38 | # @server = stderr 39 | 40 | @pid = Process.fork do 41 | io = `jstestdriver --port #{@uri.port}` 42 | 43 | Signal.trap("HUP") do 44 | puts "JsTestDriver at port #@port going down" 45 | !io.closed? && io.close! 46 | exit 47 | end 48 | end 49 | 50 | # sleep 0.5 51 | end 52 | 53 | def stop 54 | # @server && !@server.closed? && @server.close 55 | if @pid 56 | Process.kill("HUP", @pid) 57 | Process.wait 58 | end 59 | end 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'rake' 3 | 4 | begin 5 | require 'jeweler' 6 | Jeweler::Tasks.new do |gem| 7 | gem.name = "jstdutil" 8 | gem.summary = "Thin wrapper over Google's JsTestDriver that adds colors and autotest" 9 | gem.description = "Thin wrapper over Google's JsTestDriver that adds colors and autotest" 10 | gem.email = "christian@cjohansen.no" 11 | gem.homepage = "http://github.com/cjohansen/jstdutil" 12 | gem.authors = ["Christian Johansen"] 13 | gem.rubyforge_project = "jstdutil" 14 | gem.add_development_dependency "shoulda" 15 | gem.add_dependency "watchr" 16 | gem.add_dependency "rake" 17 | gem.executables = ["jstestdriver", "jsautotest"] 18 | gem.files = FileList["[A-Z]*", "{bin,generators,lib,test}/**/*"] 19 | end 20 | Jeweler::GemcutterTasks.new 21 | Jeweler::RubyforgeTasks.new do |rubyforge| 22 | rubyforge.doc_task = "rdoc" 23 | end 24 | rescue LoadError => e 25 | puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" 26 | puts e.message 27 | end 28 | 29 | require 'rake/testtask' 30 | Rake::TestTask.new(:test) do |test| 31 | test.libs << 'lib' << 'test' 32 | test.pattern = 'test/**/*_test.rb' 33 | test.verbose = true 34 | end 35 | 36 | begin 37 | require 'rcov/rcovtask' 38 | Rcov::RcovTask.new do |test| 39 | test.libs << 'test' 40 | test.pattern = 'test/**/*_test.rb' 41 | test.verbose = true 42 | end 43 | rescue LoadError 44 | task :rcov do 45 | abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov" 46 | end 47 | end 48 | 49 | task :test => :check_dependencies 50 | 51 | task :default => :test 52 | 53 | require 'rake/rdoctask' 54 | Rake::RDocTask.new do |rdoc| 55 | if File.exist?('VERSION') 56 | version = File.read('VERSION') 57 | else 58 | version = "" 59 | end 60 | 61 | rdoc.rdoc_dir = 'rdoc' 62 | rdoc.title = "jstdutil #{version}" 63 | rdoc.rdoc_files.include('README*') 64 | rdoc.rdoc_files.include('lib/**/*.rb') 65 | end 66 | -------------------------------------------------------------------------------- /lib/jstdutil/test_runner.rb: -------------------------------------------------------------------------------- 1 | require "jstdutil/jstestdriver/config" 2 | require "jstdutil/jstestdriver/server" 3 | require "jstdutil/cli" 4 | require "jstdutil/test_file" 5 | require "net/http" 6 | 7 | module Jstdutil 8 | class TestRunner 9 | def initialize(args = []) 10 | @args = strip_opt(args.join(" "), "tests") 11 | config = guess_config 12 | 13 | if config && config.server 14 | @server = JsTestDriver::Server.new(config, args({}, ["port"]).join(" ")) 15 | end 16 | rescue StandardError => err 17 | raise err 18 | end 19 | 20 | def test_cases(files) 21 | files = files.respond_to?(:captures) ? files.captures : files 22 | cases = files.collect { |file| TestFile.new(file).test_cases }.flatten.join(",") 23 | 24 | cases == "" && "all" || cases 25 | end 26 | 27 | def run(tests = "all") 28 | #begin 29 | # @server.start unless @server.running? 30 | #rescue StandardError => err 31 | # puts err.message 32 | #end 33 | if !@server.running? 34 | puts "Server not running, you want to start it with jstestdriver --port #{@server.uri.port}" 35 | exit 36 | end 37 | 38 | puts(Time.now.strftime("%F %H:%M:%S Running #{tests}")) 39 | puts(Jstdutil::Cli.run(args("tests" => tests))) 40 | end 41 | 42 | def finalize 43 | @server.stop 44 | end 45 | 46 | private 47 | def guess_config 48 | config = @args.scan(/--config\s+([^\s]+)/).flatten 49 | config = config.first || File.expand_path("jsTestDriver.conf") 50 | 51 | if !File.exists?(config) 52 | config = Dir.glob("**/jstestdriver*.conf", File::FNM_CASEFOLD) 53 | puts "Using config file #{config[0]}" if config.length > 0 54 | config = config.length > 0 ? File.expand_path(config[0]) : nil 55 | end 56 | 57 | raise ArgumentError.new("Unable to guess JsTestDriver config file, please name it jstestdriver*.conf or provide the --config option") if config.nil? 58 | 59 | @args.sub!(/(--config\s+[^\s]+)?/, "--config #{config}") 60 | 61 | JsTestDriver::Config.new(config) 62 | end 63 | 64 | def args(add = {}, remove = []) 65 | args = @args 66 | (remove + add.keys).uniq.each { |opt| args = strip_opt(args, opt) } 67 | add.each { |opt, value| args += " --#{opt} #{value}" } 68 | args.strip.split(/\s+/) 69 | end 70 | 71 | def strip_opt(str, opt) 72 | str.sub(/--#{opt}\s+[^\s]+/, "") 73 | str 74 | end 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /jstdutil.gemspec: -------------------------------------------------------------------------------- 1 | # Generated by jeweler 2 | # DO NOT EDIT THIS FILE DIRECTLY 3 | # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command 4 | # -*- encoding: utf-8 -*- 5 | 6 | Gem::Specification.new do |s| 7 | s.name = %q{jstdutil} 8 | s.version = "0.1.1" 9 | 10 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= 11 | s.authors = ["Christian Johansen"] 12 | s.date = %q{2009-11-10} 13 | s.description = %q{Thin wrapper over Google's JsTestDriver that adds colors and autotest} 14 | s.email = %q{christian@cjohansen.no} 15 | s.executables = ["jstestdriver", "jsautotest"] 16 | s.extra_rdoc_files = [ 17 | "LICENSE", 18 | "README.rdoc" 19 | ] 20 | s.files = [ 21 | "LICENSE", 22 | "README.rdoc", 23 | "Rakefile", 24 | "TODO.org", 25 | "VERSION", 26 | "bin/jsautotest", 27 | "bin/jstestdriver", 28 | "lib/jstdutil.rb", 29 | "lib/jstdutil/autotest.rb", 30 | "lib/jstdutil/cli.rb", 31 | "lib/jstdutil/hooks.rb", 32 | "lib/jstdutil/jstestdriver/config.rb", 33 | "lib/jstdutil/jstestdriver/server.rb", 34 | "lib/jstdutil/redgreen.rb", 35 | "lib/jstdutil/test_file.rb", 36 | "lib/jstdutil/test_runner.rb", 37 | "lib/watchr_script", 38 | "test/cli_test.rb", 39 | "test/jstdutil_test.rb", 40 | "test/jstestdriver_config_test.rb", 41 | "test/jstestdriver_test.rb", 42 | "test/redgreen_test.rb", 43 | "test/test_file_test.rb", 44 | "test/test_helper.rb" 45 | ] 46 | s.homepage = %q{http://github.com/cjohansen/jstdutil} 47 | s.rdoc_options = ["--charset=UTF-8"] 48 | s.require_paths = ["lib"] 49 | s.rubyforge_project = %q{jstdutil} 50 | s.rubygems_version = %q{1.3.5} 51 | s.summary = %q{Thin wrapper over Google's JsTestDriver that adds colors and autotest} 52 | s.test_files = [ 53 | "test/cli_test.rb", 54 | "test/jstdutil_test.rb", 55 | "test/jstestdriver_config_test.rb", 56 | "test/jstestdriver_test.rb", 57 | "test/redgreen_test.rb", 58 | "test/test_file_test.rb", 59 | "test/test_helper.rb" 60 | ] 61 | 62 | if s.respond_to? :specification_version then 63 | current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION 64 | s.specification_version = 3 65 | 66 | if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then 67 | s.add_development_dependency(%q, [">= 0"]) 68 | s.add_runtime_dependency(%q, [">= 0"]) 69 | s.add_runtime_dependency(%q, [">= 0"]) 70 | else 71 | s.add_dependency(%q, [">= 0"]) 72 | s.add_dependency(%q, [">= 0"]) 73 | s.add_dependency(%q, [">= 0"]) 74 | end 75 | else 76 | s.add_dependency(%q, [">= 0"]) 77 | s.add_dependency(%q, [">= 0"]) 78 | s.add_dependency(%q, [">= 0"]) 79 | end 80 | end 81 | 82 | --------------------------------------------------------------------------------