Compare commits
23 Commits
0.10.2-rel
...
0.10.4-rel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c187adc096 | ||
|
|
5aa306cf66 | ||
|
|
462b50e84e | ||
|
|
46249bf515 | ||
|
|
03d7bfb7d4 | ||
|
|
11292ff83c | ||
|
|
ab7678e713 | ||
|
|
6431431dfc | ||
|
|
a2041e90a6 | ||
|
|
ed49104fad | ||
|
|
803a2fb2ba | ||
|
|
bb1928a75c | ||
|
|
7d5ff6985f | ||
|
|
841e93fc09 | ||
|
|
5cfb019b6b | ||
|
|
9f8d18b6b7 | ||
|
|
f0574086de | ||
|
|
2212d755c3 | ||
|
|
5f10b2e623 | ||
|
|
d8ed4156c7 | ||
|
|
1469f83262 | ||
|
|
d6353a3db2 | ||
|
|
a16cbe7e5b |
@@ -5,24 +5,11 @@ Jasmine
|
||||
Quick Start
|
||||
----------
|
||||
|
||||
### Ruby Suite Running
|
||||
1. Get the latest release from the [downloads page](http://github.com/pivotal/jasmine/downloads).
|
||||
2. Open `example/example_runner.html` in your favorite browser.
|
||||
|
||||
Please use the [jasmine-ruby gem](http://github.com/pivotal/jasmine-ruby) to run suites in a ruby environment.
|
||||
|
||||
### HTML Suite Running
|
||||
[Get the latest release from the downloads page](http://github.com/pivotal/jasmine/downloads)
|
||||
|
||||
Open `example/example_runner.html` in your favorite browser.
|
||||
|
||||
### Automatic Suite Running (w/ Selenium)
|
||||
|
||||
sudo gem sources -a http://gems.github.com
|
||||
sudo gem install geminstaller
|
||||
git clone git://github.com/pivotal/jasmine.git
|
||||
cd jasmine
|
||||
sudo geminstaller
|
||||
cd examples/ruby
|
||||
rake test:ci
|
||||
For running within a Ruby environment, including automated execution with Selenium, please use
|
||||
the [jasmine-ruby gem](http://github.com/pivotal/jasmine-ruby).
|
||||
|
||||
Releases
|
||||
----------
|
||||
@@ -108,7 +95,7 @@ Jasmine has several built-in matchers. Here are a few:
|
||||
>
|
||||
>`expect(x).toBeDefined();` passes if `x` is not `undefined`
|
||||
>
|
||||
>`expect(x).toBeNull();` passes if `x` is not `null`
|
||||
>`expect(x).toBeNull();` passes if `x` is `null`
|
||||
>
|
||||
>`expect(x).toBeTruthy();` passes if `x` evaluates to true
|
||||
>
|
||||
|
||||
14
Rakefile
14
Rakefile
@@ -56,7 +56,7 @@ namespace :jasmine do
|
||||
end
|
||||
|
||||
desc 'Builds lib/jasmine from source'
|
||||
task :build => [:lint, 'gems:geminstaller'] do
|
||||
task :build => :lint do
|
||||
puts 'Building Jasmine from source'
|
||||
require 'json'
|
||||
|
||||
@@ -102,7 +102,6 @@ jasmine.version_= {
|
||||
end
|
||||
|
||||
|
||||
desc "Run jasmine tests of source via server"
|
||||
task :server do
|
||||
files = jasmine_sources + ['lib/TrivialReporter.js', 'lib/consolex.js']
|
||||
jasmine_includes = lambda {
|
||||
@@ -112,14 +111,12 @@ jasmine.version_= {
|
||||
start_jasmine_server(jasmine_includes)
|
||||
end
|
||||
|
||||
desc "Build jasmine and run tests via server"
|
||||
task :server_build => 'jasmine:build' do
|
||||
|
||||
start_jasmine_server
|
||||
end
|
||||
|
||||
namespace :test do
|
||||
desc "Run continuous integration tests using a local Selenium runner"
|
||||
task :ci => :'ci:local'
|
||||
namespace :ci do
|
||||
|
||||
@@ -133,7 +130,6 @@ jasmine.version_= {
|
||||
Rake::Task[:lambda_ci].invoke
|
||||
end
|
||||
|
||||
desc "Run continuous integration tests using Sauce Labs 'Selenium in the Cloud'"
|
||||
task :saucelabs => ['jasmine:copy_saucelabs_config', 'jasmine:build'] do
|
||||
ENV['SAUCELABS'] = 'true'
|
||||
Rake::Task['jasmine:test:ci:local'].invoke
|
||||
@@ -147,12 +143,4 @@ jasmine.version_= {
|
||||
end
|
||||
end
|
||||
|
||||
desc "Run specs via server"
|
||||
task :jasmine => ['jasmine:server']
|
||||
|
||||
namespace :gems do
|
||||
desc "Run geminstaller."
|
||||
task :geminstaller do
|
||||
`geminstaller --sudo`
|
||||
end
|
||||
end
|
||||
@@ -1,334 +0,0 @@
|
||||
require 'socket'
|
||||
require 'erb'
|
||||
require 'json'
|
||||
|
||||
module Jasmine
|
||||
def self.root
|
||||
File.expand_path(File.join(File.dirname(__FILE__), '../..'))
|
||||
end
|
||||
|
||||
# this seemingly-over-complex method is necessary to get an open port on at least some of our Macs
|
||||
def self.open_socket_on_unused_port
|
||||
infos = Socket::getaddrinfo("localhost", nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
|
||||
families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten]
|
||||
|
||||
return TCPServer.open('0.0.0.0', 0) if families.has_key?('AF_INET')
|
||||
return TCPServer.open('::', 0) if families.has_key?('AF_INET6')
|
||||
return TCPServer.open(0)
|
||||
end
|
||||
|
||||
def self.find_unused_port
|
||||
socket = open_socket_on_unused_port
|
||||
port = socket.addr[1]
|
||||
socket.close
|
||||
port
|
||||
end
|
||||
|
||||
def self.server_is_listening_on(hostname, port)
|
||||
require 'socket'
|
||||
begin
|
||||
socket = TCPSocket.open(hostname, port)
|
||||
rescue Errno::ECONNREFUSED
|
||||
return false
|
||||
end
|
||||
socket.close
|
||||
true
|
||||
end
|
||||
|
||||
def self.wait_for_listener(port, name = "required process", seconds_to_wait = 10)
|
||||
time_out_at = Time.now + seconds_to_wait
|
||||
until server_is_listening_on "localhost", port
|
||||
sleep 0.1
|
||||
puts "Waiting for #{name} on #{port}..."
|
||||
raise "#{name} didn't show up on port #{port} after #{seconds_to_wait} seconds." if Time.now > time_out_at
|
||||
end
|
||||
end
|
||||
|
||||
def self.kill_process_group(process_group_id, signal="TERM")
|
||||
Process.kill signal, -process_group_id # negative pid means kill process group. (see man 2 kill)
|
||||
end
|
||||
|
||||
def self.cachebust(files, root_dir="", replace=nil, replace_with=nil)
|
||||
require 'digest/md5'
|
||||
files.collect do |file_name|
|
||||
real_file_name = replace && replace_with ? file_name.sub(replace, replace_with) : file_name
|
||||
begin
|
||||
digest = Digest::MD5.hexdigest(File.read("#{root_dir}#{real_file_name}"))
|
||||
rescue
|
||||
digest = "MISSING-FILE"
|
||||
end
|
||||
"#{file_name}?cachebust=#{digest}"
|
||||
end
|
||||
end
|
||||
|
||||
class RunAdapter
|
||||
def initialize(spec_files_or_proc, options = {})
|
||||
@spec_files_or_proc = Jasmine.files(spec_files_or_proc) || []
|
||||
@jasmine_files = Jasmine.files(options[:jasmine_files]) || [
|
||||
"/__JASMINE_ROOT__/lib/" + File.basename(Dir.glob("#{Jasmine.root}/lib/jasmine*.js").first),
|
||||
"/__JASMINE_ROOT__/lib/TrivialReporter.js",
|
||||
"/__JASMINE_ROOT__/lib/json2.js",
|
||||
"/__JASMINE_ROOT__/lib/consolex.js",
|
||||
]
|
||||
@stylesheets = ["/__JASMINE_ROOT__/lib/jasmine.css"] + (Jasmine.files(options[:stylesheets]) || [])
|
||||
@spec_helpers = Jasmine.files(options[:spec_helpers]) || []
|
||||
end
|
||||
|
||||
def call(env)
|
||||
run
|
||||
end
|
||||
|
||||
def run
|
||||
stylesheets = @stylesheets
|
||||
spec_helpers = @spec_helpers
|
||||
spec_files = @spec_files_or_proc
|
||||
|
||||
jasmine_files = @jasmine_files
|
||||
jasmine_files = jasmine_files.call if jasmine_files.respond_to?(:call)
|
||||
|
||||
css_files = @stylesheets
|
||||
|
||||
|
||||
body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html"))).result(binding)
|
||||
[
|
||||
200,
|
||||
{ 'Content-Type' => 'text/html' },
|
||||
body
|
||||
]
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
class Redirect
|
||||
def initialize(url)
|
||||
@url = url
|
||||
end
|
||||
|
||||
def call(env)
|
||||
[
|
||||
302,
|
||||
{ 'Location' => @url },
|
||||
[]
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
class JsAlert
|
||||
def call(env)
|
||||
[
|
||||
200,
|
||||
{ 'Content-Type' => 'application/javascript' },
|
||||
"document.write('<p>Couldn\\'t load #{env["PATH_INFO"]}!</p>');"
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
class FocusedSuite
|
||||
def initialize(spec_files_or_proc, options)
|
||||
@spec_files_or_proc = Jasmine.files(spec_files_or_proc) || []
|
||||
@options = options
|
||||
end
|
||||
|
||||
def call(env)
|
||||
spec_files = @spec_files_or_proc
|
||||
matching_specs = spec_files.select {|spec_file| spec_file =~ /#{Regexp.escape(env["PATH_INFO"])}/ }.compact
|
||||
if !matching_specs.empty?
|
||||
run_adapter = Jasmine::RunAdapter.new(matching_specs, @options)
|
||||
run_adapter.run
|
||||
else
|
||||
[
|
||||
200,
|
||||
{ 'Content-Type' => 'application/javascript' },
|
||||
"document.write('<p>Couldn\\'t find any specs matching #{env["PATH_INFO"]}!</p>');"
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class SimpleServer
|
||||
def self.start(port, spec_files_or_proc, mappings, options = {})
|
||||
require 'thin'
|
||||
config = {
|
||||
'/__suite__' => Jasmine::FocusedSuite.new(spec_files_or_proc, options),
|
||||
'/run.html' => Jasmine::Redirect.new('/'),
|
||||
'/' => Jasmine::RunAdapter.new(spec_files_or_proc, options)
|
||||
}
|
||||
mappings.each do |from, to|
|
||||
config[from] = Rack::File.new(to)
|
||||
end
|
||||
|
||||
config["/__JASMINE_ROOT__"] = Rack::File.new(Jasmine.root)
|
||||
|
||||
app = Rack::Cascade.new([
|
||||
Rack::URLMap.new(config),
|
||||
JsAlert.new
|
||||
])
|
||||
|
||||
begin
|
||||
Thin::Server.start('0.0.0.0', port, app)
|
||||
rescue RuntimeError => e
|
||||
raise e unless e.message == 'no acceptor'
|
||||
raise RuntimeError.new("A server is already running on port #{port}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class SimpleClient
|
||||
def initialize(selenium_host, selenium_port, selenium_browser_start_command, http_address)
|
||||
require 'selenium/client'
|
||||
@driver = Selenium::Client::Driver.new(
|
||||
selenium_host,
|
||||
selenium_port,
|
||||
selenium_browser_start_command,
|
||||
http_address
|
||||
)
|
||||
@http_address = http_address
|
||||
end
|
||||
|
||||
def tests_have_finished?
|
||||
@driver.get_eval("window.jasmine.getEnv().currentRunner.finished") == "true"
|
||||
end
|
||||
|
||||
def connect
|
||||
@driver.start
|
||||
@driver.open("/")
|
||||
end
|
||||
|
||||
def disconnect
|
||||
@driver.stop
|
||||
end
|
||||
|
||||
def run
|
||||
until tests_have_finished? do
|
||||
sleep 0.1
|
||||
end
|
||||
|
||||
puts @driver.get_eval("window.results()")
|
||||
failed_count = @driver.get_eval("window.jasmine.getEnv().currentRunner.results().failedCount").to_i
|
||||
failed_count == 0
|
||||
end
|
||||
|
||||
def eval_js(script)
|
||||
escaped_script = "'" + script.gsub(/(['\\])/) { '\\' + $1 } + "'"
|
||||
|
||||
result = @driver.get_eval(" try { eval(#{escaped_script}, window); } catch(err) { window.eval(#{escaped_script}); }")
|
||||
JSON.parse("[#{result}]")[0]
|
||||
end
|
||||
end
|
||||
|
||||
class Runner
|
||||
def initialize(selenium_jar_path, spec_files, dir_mappings, options={})
|
||||
@selenium_jar_path = selenium_jar_path
|
||||
@spec_files = spec_files
|
||||
@dir_mappings = dir_mappings
|
||||
@options = options
|
||||
|
||||
@browser = options[:browser] ? options[:browser].delete(:browser) : 'firefox'
|
||||
@selenium_pid = nil
|
||||
@jasmine_server_pid = nil
|
||||
@selenium_host = 'localhost'
|
||||
@jasmine_server_port = Jasmine::find_unused_port
|
||||
@selenium_server_port = Jasmine::find_unused_port
|
||||
end
|
||||
|
||||
def start
|
||||
start_jasmine_server
|
||||
start_selenium_server
|
||||
@client = Jasmine::SimpleClient.new(@selenium_host, @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/")
|
||||
@client.connect
|
||||
end
|
||||
|
||||
def stop
|
||||
@client.disconnect
|
||||
stop_selenium_server
|
||||
stop_jasmine_server
|
||||
end
|
||||
|
||||
def start_jasmine_server
|
||||
@jasmine_server_pid = fork do
|
||||
Process.setpgrp
|
||||
Jasmine::SimpleServer.start(@jasmine_server_port, @spec_files, @dir_mappings, @options)
|
||||
exit! 0
|
||||
end
|
||||
puts "jasmine server started. pid is #{@jasmine_server_pid}"
|
||||
Jasmine::wait_for_listener(@jasmine_server_port, "jasmine server")
|
||||
end
|
||||
|
||||
def start_selenium_server
|
||||
@selenium_pid = fork do
|
||||
Process.setpgrp
|
||||
exec "java -jar #{@selenium_jar_path} -port #{@selenium_server_port} > /dev/null 2>&1"
|
||||
end
|
||||
puts "selenium started. pid is #{@selenium_pid}"
|
||||
Jasmine::wait_for_listener(@selenium_server_port, "selenium server")
|
||||
end
|
||||
|
||||
def stop_jasmine_server
|
||||
puts "shutting down Jasmine server..."
|
||||
Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_pid
|
||||
end
|
||||
|
||||
def stop_selenium_server
|
||||
puts "shutting down Selenium server..."
|
||||
Jasmine::kill_process_group(@selenium_pid) if @selenium_pid
|
||||
end
|
||||
|
||||
def run
|
||||
begin
|
||||
start
|
||||
puts "servers are listening on their ports -- running the test script..."
|
||||
tests_passed = @client.run
|
||||
ensure
|
||||
stop
|
||||
end
|
||||
return tests_passed
|
||||
end
|
||||
|
||||
def eval_js(script)
|
||||
@client.eval_js(script)
|
||||
end
|
||||
end
|
||||
|
||||
class SauceLabsRunner < Runner
|
||||
def initialize(spec_files, dir_mappings, options={})
|
||||
@spec_files = spec_files
|
||||
@dir_mappings = dir_mappings
|
||||
@options = options
|
||||
|
||||
@browser = options[:browser] ? options[:browser].delete(:browser) : 'firefox'
|
||||
@jasmine_server_pid = nil
|
||||
@jasmine_server_port = Jasmine::find_unused_port
|
||||
@saucelabs_config = SeleniumConfig.new(options[:saucelabs_config], options[:saucelabs_config_file], @jasmine_server_port)
|
||||
end
|
||||
|
||||
def start_selenium_server
|
||||
@sauce_tunnel = SauceTunnel.new(@saucelabs_config)
|
||||
end
|
||||
|
||||
def start
|
||||
start_jasmine_server
|
||||
start_selenium_server
|
||||
@client = Jasmine::SimpleClient.new(@saucelabs_config['selenium_server_address'],
|
||||
4444,
|
||||
@saucelabs_config['selenium_browser_key'],
|
||||
"http://#{@saucelabs_config['application_address']}")
|
||||
@client.connect
|
||||
end
|
||||
|
||||
def stop
|
||||
@client.disconnect
|
||||
@sauce_tunnel.shutdown
|
||||
stop_jasmine_server
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def self.files(f)
|
||||
result = f
|
||||
result = result.call if result.respond_to?(:call)
|
||||
result
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,153 +0,0 @@
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), "jasmine_runner.rb"))
|
||||
require 'enumerator'
|
||||
module Jasmine
|
||||
|
||||
class SpecBuilder
|
||||
attr_accessor :suites
|
||||
|
||||
def initialize(spec_files, runner)
|
||||
@spec_files = spec_files
|
||||
@runner = runner
|
||||
@spec_ids = []
|
||||
end
|
||||
|
||||
def start
|
||||
guess_example_locations
|
||||
|
||||
@runner.start
|
||||
load_suite_info
|
||||
wait_for_suites_to_finish_running
|
||||
end
|
||||
|
||||
def stop
|
||||
@runner.stop
|
||||
end
|
||||
|
||||
def script_path
|
||||
File.expand_path(__FILE__)
|
||||
end
|
||||
|
||||
def guess_example_locations
|
||||
@example_locations = {}
|
||||
|
||||
example_name_parts = []
|
||||
previous_indent_level = 0
|
||||
@spec_files.each do |filename|
|
||||
line_number = 1
|
||||
File.open(filename, "r") do |file|
|
||||
file.readlines.each do |line|
|
||||
match = /^(\s*)(describe|it)\s*\(\s*["'](.*)["']\s*,\s*function/.match(line)
|
||||
if (match)
|
||||
indent_level = match[1].length / 2
|
||||
example_name = match[3]
|
||||
example_name_parts[indent_level] = example_name
|
||||
|
||||
full_example_name = example_name_parts.slice(0, indent_level + 1).join(" ")
|
||||
@example_locations[full_example_name] = "#{filename}:#{line_number}: in `it'"
|
||||
end
|
||||
line_number += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def load_suite_info
|
||||
started = Time.now
|
||||
while !eval_js('jsApiReporter && jsApiReporter.started') do
|
||||
raise "couldn't connect to Jasmine after 60 seconds" if (started + 60 < Time.now)
|
||||
sleep 0.1
|
||||
end
|
||||
|
||||
@suites = eval_js("var result = jsApiReporter.suites(); if (window.Prototype && result && result.toJSON) { result.toJSON()} else { JSON.stringify(result) }")
|
||||
end
|
||||
|
||||
def results_for(spec_id)
|
||||
@spec_results ||= load_results
|
||||
@spec_results[spec_id.to_s]
|
||||
end
|
||||
|
||||
def load_results
|
||||
@spec_results = {}
|
||||
@spec_ids.each_slice(50) do |slice|
|
||||
@spec_results.merge!(eval_js("var result = jsApiReporter.resultsForSpecs(#{JSON.generate(slice)}); if (window.Prototype && result && result.toJSON) { result.toJSON()} else { JSON.stringify(result) }"))
|
||||
end
|
||||
@spec_results
|
||||
end
|
||||
|
||||
def wait_for_suites_to_finish_running
|
||||
puts "Waiting for suite to finish in browser ..."
|
||||
while !eval_js('jsApiReporter.finished') do
|
||||
sleep 0.1
|
||||
end
|
||||
end
|
||||
|
||||
def declare_suites
|
||||
me = self
|
||||
suites.each do |suite|
|
||||
declare_suite(self, suite)
|
||||
end
|
||||
end
|
||||
|
||||
def declare_suite(parent, suite)
|
||||
me = self
|
||||
parent.describe suite["name"] do
|
||||
suite["children"].each do |suite_or_spec|
|
||||
type = suite_or_spec["type"]
|
||||
if type == "suite"
|
||||
me.declare_suite(self, suite_or_spec)
|
||||
elsif type == "spec"
|
||||
me.declare_spec(self, suite_or_spec)
|
||||
else
|
||||
raise "unknown type #{type} for #{suite_or_spec.inspect}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def declare_spec(parent, spec)
|
||||
me = self
|
||||
example_name = spec["name"]
|
||||
@spec_ids << spec["id"]
|
||||
backtrace = @example_locations[parent.description + " " + example_name]
|
||||
parent.it example_name, {}, backtrace do
|
||||
me.report_spec(spec["id"])
|
||||
end
|
||||
end
|
||||
|
||||
def report_spec(spec_id)
|
||||
spec_results = results_for(spec_id)
|
||||
|
||||
out = ""
|
||||
messages = spec_results['messages'].each do |message|
|
||||
case
|
||||
when message["type"] == "MessageResult"
|
||||
puts message["text"]
|
||||
puts "\n"
|
||||
else
|
||||
unless message["message"] =~ /^Passed.$/
|
||||
STDERR << message["message"]
|
||||
STDERR << "\n"
|
||||
|
||||
out << message["message"]
|
||||
out << "\n"
|
||||
end
|
||||
|
||||
if !message["passed"] && message["trace"]["stack"]
|
||||
stack_trace = message["trace"]["stack"].gsub(/<br \/>/, "\n").gsub(/<\/?b>/, " ")
|
||||
STDERR << stack_trace.gsub(/\(.*\)@http:\/\/localhost:[0-9]+\/specs\//, "/spec/")
|
||||
STDERR << "\n"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
fail out unless spec_results['result'] == 'passed'
|
||||
puts out unless out.empty?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def eval_js(js)
|
||||
@runner.eval_js(js)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,47 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type"/>
|
||||
<title>Jasmine suite</title>
|
||||
<% css_files.each do |css_file| %>
|
||||
<link rel="stylesheet" href="<%= css_file %>" type="text/css" media="screen"/>
|
||||
<% end %>
|
||||
|
||||
<% jasmine_files.each do |jasmine_file| %>
|
||||
<script src="<%= jasmine_file %>" type="text/javascript"></script>
|
||||
<% end %>
|
||||
|
||||
<% spec_helpers.each do |spec_helper| %>
|
||||
<script src="<%= spec_helper %>" type="text/javascript"></script>
|
||||
<% end %>
|
||||
|
||||
<script type="text/javascript">
|
||||
var jsApiReporter;
|
||||
(function() {
|
||||
var jasmineEnv = jasmine.getEnv();
|
||||
|
||||
jsApiReporter = new jasmine.JsApiReporter();
|
||||
var trivialReporter = new jasmine.TrivialReporter();
|
||||
|
||||
jasmineEnv.addReporter(jsApiReporter);
|
||||
jasmineEnv.addReporter(trivialReporter);
|
||||
|
||||
jasmineEnv.specFilter = function(spec) {
|
||||
return trivialReporter.specFilter(spec);
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
jasmineEnv.execute();
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
|
||||
<% spec_files.each do |spec_file| %>
|
||||
<script src="<%= spec_file %>" type="text/javascript"></script>
|
||||
<% end %>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="jasmine_content"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,71 +0,0 @@
|
||||
require 'spec'
|
||||
require 'open-uri'
|
||||
require 'thin'
|
||||
|
||||
require File.dirname(__FILE__) + '/../jasmine_runner'
|
||||
|
||||
describe Jasmine::SimpleServer do
|
||||
before do
|
||||
@port = Jasmine::find_unused_port
|
||||
end
|
||||
|
||||
after do
|
||||
Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_pid
|
||||
end
|
||||
|
||||
it "should start and print script tags" do
|
||||
@jasmine_server_pid = fork do
|
||||
Process.setpgrp
|
||||
Jasmine::SimpleServer.start(@port, ["file1", "file2"], {})
|
||||
exit! 0
|
||||
end
|
||||
|
||||
Jasmine::wait_for_listener(@port)
|
||||
|
||||
run_html = open("http://localhost:#{@port}/").read
|
||||
run_html.should =~ /<script src="file1"/
|
||||
run_html.should =~ /<script src="file2"/
|
||||
end
|
||||
|
||||
describe "RuntimeError" do
|
||||
|
||||
it "should throw an Already Running error if there is already a server running" do
|
||||
Thin::Server.should_receive(:start).and_raise(RuntimeError.new('no acceptor'))
|
||||
lambda {
|
||||
Jasmine::SimpleServer.start(@port, ["file1", "file2"], {})
|
||||
}.should raise_error(RuntimeError, "A server is already running on port #{@port}")
|
||||
end
|
||||
|
||||
it "re-raises other RuntimeErrors" do
|
||||
Thin::Server.should_receive(:start).and_raise(RuntimeError.new('some random error'))
|
||||
lambda {
|
||||
Jasmine::SimpleServer.start(@port, ["file1", "file2"], {})
|
||||
}.should raise_error(RuntimeError, "some random error")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
it "should take a proc that returns a list of spec files" do
|
||||
spec_fileses = [["file1", "file2"], ["file1", "file2", "file3"]]
|
||||
spec_files_proc = lambda do
|
||||
spec_fileses.shift
|
||||
end
|
||||
|
||||
@jasmine_server_pid = fork do
|
||||
Process.setpgrp
|
||||
Jasmine::SimpleServer.start(@port, spec_files_proc, {})
|
||||
exit! 0
|
||||
end
|
||||
|
||||
Jasmine::wait_for_listener(@port)
|
||||
|
||||
run_html = open("http://localhost:#{@port}/").read
|
||||
run_html.should =~ /<script src="file1"/
|
||||
run_html.should =~ /<script src="file2"/
|
||||
|
||||
run_html = open("http://localhost:#{@port}/").read
|
||||
run_html.should =~ /<script src="file1"/
|
||||
run_html.should =~ /<script src="file2"/
|
||||
run_html.should =~ /<script src="file3"/
|
||||
end
|
||||
end
|
||||
@@ -3,18 +3,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Jasmine Test Runner</title>
|
||||
<link rel="stylesheet" type="text/css" href="../lib/jasmine.css">
|
||||
<script type="text/javascript" src="../lib/jasmine-0.10.4.js"></script>
|
||||
<script type="text/javascript" src="../lib/TrivialReporter.js"></script>
|
||||
<script type="text/javascript" src="../lib/consolex.js"></script>
|
||||
<script type="text/javascript" src="spec/example_suite.js"></script>
|
||||
</head>
|
||||
<script type="text/javascript" src="../../lib/jasmine-0.10.1.js"></script>
|
||||
<script type="text/javascript" src="../../lib/TrivialReporter.js"></script>
|
||||
<script type="text/javascript" src="../../lib/consolex.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../../lib/jasmine.css">
|
||||
|
||||
<script type="text/javascript">
|
||||
jasmine.include('spec/example_suite.js', true);
|
||||
</script>
|
||||
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var jasmineEnv = jasmine.getEnv();
|
||||
jasmineEnv.reporter = new jasmine.TrivialReporter();
|
||||
@@ -1,33 +0,0 @@
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), "spec/jasmine_helper.rb"))
|
||||
|
||||
namespace :test do
|
||||
desc "Run continuous integration tests"
|
||||
task :ci => :'ci:local'
|
||||
namespace :ci do
|
||||
require "spec"
|
||||
require 'spec/rake/spectask'
|
||||
|
||||
Spec::Rake::SpecTask.new(:local) do |t|
|
||||
t.spec_opts = ["--color", "--format", "specdoc"]
|
||||
t.spec_files = ["spec/jasmine_spec.rb"]
|
||||
end
|
||||
|
||||
desc "Run continuous integration tests using Sauce Labs 'Selenium in the Cloud'"
|
||||
task :saucelabs do
|
||||
ENV['SAUCELABS'] = 'true'
|
||||
Rake::Task['test:ci:local'].invoke
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc "Run specs via server"
|
||||
task :jasmine_server do
|
||||
require File.expand_path(File.join(JasmineHelper.jasmine_root, "contrib/ruby/jasmine_spec_builder"))
|
||||
|
||||
puts "your tests are here:"
|
||||
puts " http://localhost:8888/run.html"
|
||||
|
||||
Jasmine::SimpleServer.start(8888,
|
||||
lambda { JasmineHelper.specs },
|
||||
JasmineHelper.dir_mappings)
|
||||
end
|
||||
@@ -1,11 +0,0 @@
|
||||
describe('ExampleSuite', function () {
|
||||
it('should have a passing test', function() {
|
||||
expect(true).toEqual(true);
|
||||
});
|
||||
|
||||
describe('Nested Describe', function () {
|
||||
it('should also have a passing test', function () {
|
||||
expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,41 +0,0 @@
|
||||
class JasmineHelper
|
||||
def self.jasmine_lib_dir
|
||||
File.expand_path(File.join(jasmine_root, 'lib'))
|
||||
end
|
||||
|
||||
def self.jasmine_root
|
||||
File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..'))
|
||||
end
|
||||
|
||||
def self.jasmine
|
||||
['/lib/' + File.basename(Dir.glob("#{JasmineHelper.jasmine_lib_dir}/jasmine*.js").first)] +
|
||||
['/lib/json2.js',
|
||||
'/lib/TrivialReporter.js',
|
||||
'/lib/consolex.js'
|
||||
]
|
||||
end
|
||||
|
||||
def self.jasmine_src_dir
|
||||
File.expand_path(File.join(jasmine_root, 'src'))
|
||||
end
|
||||
|
||||
def self.jasmine_spec_dir
|
||||
File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec'))
|
||||
end
|
||||
|
||||
def self.raw_spec_files
|
||||
Dir.glob(File.join(jasmine_spec_dir, "**/*[Ss]pec.js"))
|
||||
end
|
||||
|
||||
def self.specs
|
||||
raw_spec_files.collect {|f| f.sub(jasmine_spec_dir, "/spec")}
|
||||
end
|
||||
|
||||
def self.dir_mappings
|
||||
{
|
||||
"/src" => jasmine_src_dir,
|
||||
"/spec" => jasmine_spec_dir,
|
||||
"/lib" => jasmine_lib_dir
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -1,31 +0,0 @@
|
||||
require 'rubygems'
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), "jasmine_helper.rb"))
|
||||
require File.expand_path(File.join(JasmineHelper.jasmine_root, "contrib/ruby/jasmine_spec_builder"))
|
||||
|
||||
jasmine_runner = if ENV['SAUCELABS'] == 'true'
|
||||
require 'sauce_tunnel'
|
||||
require 'selenium_config'
|
||||
Jasmine::SauceLabsRunner.new(JasmineHelper.specs,
|
||||
JasmineHelper.dir_mappings,
|
||||
:saucelabs_config => 'saucelabs',
|
||||
:saucelabs_config_file => File.expand_path(File.join(File.dirname(__FILE__), "saucelabs.yml")))
|
||||
else
|
||||
require "selenium_rc"
|
||||
Jasmine::Runner.new(SeleniumRC::Server.new('localhost').jar_path,
|
||||
JasmineHelper.specs,
|
||||
JasmineHelper.dir_mappings)
|
||||
end
|
||||
|
||||
spec_builder = Jasmine::SpecBuilder.new(JasmineHelper.raw_spec_files, jasmine_runner)
|
||||
|
||||
should_stop = false
|
||||
|
||||
Spec::Runner.configure do |config|
|
||||
config.after(:suite) do
|
||||
spec_builder.stop if should_stop
|
||||
end
|
||||
end
|
||||
|
||||
spec_builder.start
|
||||
should_stop = true
|
||||
spec_builder.declare_suites
|
||||
@@ -1,24 +0,0 @@
|
||||
local:
|
||||
application_framework: :selenium
|
||||
#
|
||||
# Possible Sauce Labs configurations as of 2009/11/19
|
||||
# From: http://saucelabs.com/products/docs/sauce-ondemand/browsers
|
||||
# os: "Windows 2003"
|
||||
# browser: "iexplore"
|
||||
# browser-version: "6.", "7.", "8."
|
||||
# browser: "firefox"
|
||||
# browser-version: "2.", "3.0", "3.5"
|
||||
# browser: "safari"
|
||||
# browser-version: "3.", "4."
|
||||
# browser: "opera"
|
||||
# browser-version: "9."
|
||||
# browser: "googlechrome"
|
||||
# browser-version: ""
|
||||
# os: "Linux"
|
||||
# browser: "firefox"
|
||||
# browser-version: "3."
|
||||
saucelabs:
|
||||
application_framework: :external
|
||||
selenium_server_address: "saucelabs.com"
|
||||
selenium_browser_key: '{"username": "--YOUR-SAUCELABS-USERNAME--", "access-key": "--YOUR-SAUCELABS-ACCESS-KEY--", "os": "Linux", "browser": "firefox", "browser-version": "3."}'
|
||||
application_port: "80"
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
gems:
|
||||
- name: rake
|
||||
version: 0.8.7
|
||||
- name: ragaskar-jsdoc_helper
|
||||
version: 0.0.2.1
|
||||
- name: json
|
||||
version: 1.1.9
|
||||
- name: selenium-rc
|
||||
version: 2.2.0
|
||||
- name: rack
|
||||
version: 1.0.0
|
||||
- name: thin
|
||||
version: 1.2.4
|
||||
- name: eventmachine
|
||||
version: 0.12.8
|
||||
- name: rspec
|
||||
version: 1.2.9
|
||||
- name: selenium-client
|
||||
version: 1.2.18
|
||||
- name: rest-client
|
||||
version: 1.0.3
|
||||
- name: saucelabs-adapter
|
||||
version: 0.3.2
|
||||
install_options: --source=http://gems.pivotallabs.com
|
||||
@@ -17,7 +17,11 @@ jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarA
|
||||
}
|
||||
|
||||
for (var attr in attrs) {
|
||||
if (attr == "className") {
|
||||
el[attr] = attrs[attr];
|
||||
} else {
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
@@ -26,10 +30,29 @@ jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarA
|
||||
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
||||
var suites = runner.suites();
|
||||
|
||||
this.runnerDiv = this.createDom('div', { className: 'runner running' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
|
||||
this.runnerMessageSpan = this.createDom('span', {}, "Running..."));
|
||||
this.document.body.appendChild(this.runnerDiv);
|
||||
var showPassed, showSkipped;
|
||||
|
||||
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
|
||||
this.createDom('div', { className: 'banner' },
|
||||
this.createDom('div', { className: 'logo' },
|
||||
"Jasmine",
|
||||
this.createDom('span', { className: 'version' }, runner.env.versionString())),
|
||||
this.createDom('div', { className: 'options' },
|
||||
"Show ",
|
||||
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
|
||||
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
|
||||
)
|
||||
),
|
||||
|
||||
this.runnerDiv = this.createDom('div', { className: 'runner running' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
|
||||
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
|
||||
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
|
||||
);
|
||||
|
||||
this.document.body.appendChild(this.outerDiv);
|
||||
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
var suite = suites[i];
|
||||
@@ -37,7 +60,7 @@ jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
|
||||
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
|
||||
this.suiteDivs[suite.getFullName()] = suiteDiv;
|
||||
var parentDiv = this.document.body;
|
||||
var parentDiv = this.outerDiv;
|
||||
if (suite.parentSuite) {
|
||||
parentDiv = this.suiteDivs[suite.parentSuite.getFullName()];
|
||||
}
|
||||
@@ -45,6 +68,23 @@ jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
||||
}
|
||||
|
||||
this.startedAt = new Date();
|
||||
|
||||
var self = this;
|
||||
showPassed.onchange = function(evt) {
|
||||
if (evt.target.checked) {
|
||||
self.outerDiv.className += ' show-passed';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
|
||||
}
|
||||
};
|
||||
|
||||
showSkipped.onchange = function(evt) {
|
||||
if (evt.target.checked) {
|
||||
self.outerDiv.className += ' show-skipped';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
|
||||
@@ -63,6 +103,8 @@ jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
|
||||
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
|
||||
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
|
||||
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
|
||||
|
||||
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
|
||||
@@ -82,17 +124,30 @@ jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
|
||||
}
|
||||
var specDiv = this.createDom('div', { className: 'spec ' + status },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
|
||||
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, spec.getFullName()));
|
||||
this.createDom('a', {
|
||||
className: 'description',
|
||||
href: '?spec=' + encodeURIComponent(spec.getFullName()),
|
||||
title: spec.getFullName()
|
||||
}, spec.description));
|
||||
|
||||
|
||||
var resultItems = results.getItems();
|
||||
var messagesDiv = this.createDom('div', { className: 'messages' });
|
||||
for (var i = 0; i < resultItems.length; i++) {
|
||||
var result = resultItems[i];
|
||||
if (result.passed && !result.passed()) {
|
||||
specDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
||||
specDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
||||
|
||||
if (result.trace.stack) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messagesDiv.childNodes.length > 0) {
|
||||
specDiv.appendChild(messagesDiv);
|
||||
}
|
||||
|
||||
this.suiteDivs[spec.suite.getFullName()].appendChild(specDiv);
|
||||
};
|
||||
|
||||
@@ -114,4 +169,4 @@ jasmine.TrivialReporter.prototype.specFilter = function(spec) {
|
||||
|
||||
if (!paramMap["spec"]) return true;
|
||||
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ jasmine.unimplementedMethod_ = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code is just
|
||||
* Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
|
||||
* a plain old variable and may be redefined by somebody else.
|
||||
*
|
||||
* @private
|
||||
@@ -57,6 +57,10 @@ jasmine.MessageResult = function(text) {
|
||||
this.trace = new Error(); // todo: test better
|
||||
};
|
||||
|
||||
jasmine.MessageResult.prototype.toString = function() {
|
||||
return this.text;
|
||||
};
|
||||
|
||||
jasmine.ExpectationResult = function(params) {
|
||||
this.type = 'ExpectationResult';
|
||||
this.matcherName = params.matcherName;
|
||||
@@ -71,6 +75,10 @@ jasmine.ExpectationResult = function(params) {
|
||||
this.trace = this.passed_ ? '' : new Error(this.message);
|
||||
};
|
||||
|
||||
jasmine.ExpectationResult.prototype.toString = function () {
|
||||
return this.message;
|
||||
};
|
||||
|
||||
jasmine.ExpectationResult.prototype.passed = function () {
|
||||
return this.passed_;
|
||||
};
|
||||
@@ -558,6 +566,7 @@ jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
|
||||
*
|
||||
* @param {String} url path to the file to include
|
||||
* @param {Boolean} opt_global
|
||||
* @deprecated We suggest you use a different method of including JS source files. <code>jasmine.include</code> will be removed soon.
|
||||
*/
|
||||
jasmine.include = function(url, opt_global) {
|
||||
if (opt_global) {
|
||||
@@ -690,6 +699,18 @@ jasmine.Env.prototype.version = function () {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns string containing jasmine version build info, if set.
|
||||
*/
|
||||
jasmine.Env.prototype.versionString = function() {
|
||||
if (jasmine.version_) {
|
||||
var version = this.version();
|
||||
return version.major + "." + version.minor + "." + version.build + " revision " + version.revision;
|
||||
} else {
|
||||
return "version unknown";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns a sequential integer starting at 0
|
||||
*/
|
||||
@@ -728,10 +749,21 @@ jasmine.Env.prototype.describe = function(description, specDefinitions) {
|
||||
|
||||
this.currentSuite = suite;
|
||||
|
||||
specDefinitions.call(suite);
|
||||
var declarationError = null;
|
||||
try {
|
||||
specDefinitions.call(suite);
|
||||
} catch(e) {
|
||||
declarationError = e;
|
||||
}
|
||||
|
||||
this.currentSuite = parentSuite;
|
||||
|
||||
if (declarationError) {
|
||||
this.it("encountered a declaration exception", function() {
|
||||
throw declarationError;
|
||||
});
|
||||
}
|
||||
|
||||
return suite;
|
||||
};
|
||||
|
||||
@@ -1764,12 +1796,12 @@ jasmine.Runner.prototype.execute = function() {
|
||||
|
||||
jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
|
||||
beforeEachFunction.typeName = 'beforeEach';
|
||||
this.before_.push(beforeEachFunction);
|
||||
this.before_.splice(0,0,beforeEachFunction);
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
|
||||
afterEachFunction.typeName = 'afterEach';
|
||||
this.after_.push(afterEachFunction);
|
||||
this.after_.splice(0,0,afterEachFunction);
|
||||
};
|
||||
|
||||
|
||||
@@ -2050,12 +2082,12 @@ jasmine.Suite.prototype.finish = function(onComplete) {
|
||||
|
||||
jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
|
||||
beforeEachFunction.typeName = 'beforeEach';
|
||||
this.before_.push(beforeEachFunction);
|
||||
this.before_.unshift(beforeEachFunction);
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
|
||||
afterEachFunction.typeName = 'afterEach';
|
||||
this.after_.push(afterEachFunction);
|
||||
this.after_.unshift(afterEachFunction);
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.results = function() {
|
||||
@@ -2126,193 +2158,192 @@ jasmine.WaitsForBlock.prototype.execute = function (onComplete) {
|
||||
name: 'timeout',
|
||||
message: message
|
||||
});
|
||||
self.spec._next();
|
||||
} else {
|
||||
self.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
|
||||
self.env.setTimeout(function () { self.execute(onComplete); }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
|
||||
}
|
||||
};
|
||||
// Mock setTimeout, clearTimeout
|
||||
// Contributed by Pivotal Computer Systems, www.pivotalsf.com
|
||||
|
||||
jasmine.FakeTimer = function() {
|
||||
this.reset();
|
||||
|
||||
var self = this;
|
||||
self.setTimeout = function(funcToCall, millis) {
|
||||
self.timeoutsMade++;
|
||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
|
||||
return self.timeoutsMade;
|
||||
};
|
||||
|
||||
self.setInterval = function(funcToCall, millis) {
|
||||
self.timeoutsMade++;
|
||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
|
||||
return self.timeoutsMade;
|
||||
};
|
||||
|
||||
self.clearTimeout = function(timeoutKey) {
|
||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
||||
};
|
||||
|
||||
self.clearInterval = function(timeoutKey) {
|
||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.reset = function() {
|
||||
this.timeoutsMade = 0;
|
||||
this.scheduledFunctions = {};
|
||||
this.nowMillis = 0;
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.tick = function(millis) {
|
||||
var oldMillis = this.nowMillis;
|
||||
var newMillis = oldMillis + millis;
|
||||
this.runFunctionsWithinRange(oldMillis, newMillis);
|
||||
this.nowMillis = newMillis;
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
|
||||
var scheduledFunc;
|
||||
var funcsToRun = [];
|
||||
for (var timeoutKey in this.scheduledFunctions) {
|
||||
scheduledFunc = this.scheduledFunctions[timeoutKey];
|
||||
if (scheduledFunc != jasmine.undefined &&
|
||||
scheduledFunc.runAtMillis >= oldMillis &&
|
||||
scheduledFunc.runAtMillis <= nowMillis) {
|
||||
funcsToRun.push(scheduledFunc);
|
||||
this.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (funcsToRun.length > 0) {
|
||||
funcsToRun.sort(function(a, b) {
|
||||
return a.runAtMillis - b.runAtMillis;
|
||||
});
|
||||
for (var i = 0; i < funcsToRun.length; ++i) {
|
||||
try {
|
||||
var funcToRun = funcsToRun[i];
|
||||
this.nowMillis = funcToRun.runAtMillis;
|
||||
funcToRun.funcToCall();
|
||||
if (funcToRun.recurring) {
|
||||
this.scheduleFunction(funcToRun.timeoutKey,
|
||||
funcToRun.funcToCall,
|
||||
funcToRun.millis,
|
||||
true);
|
||||
}
|
||||
} catch(e) {
|
||||
}
|
||||
}
|
||||
this.runFunctionsWithinRange(oldMillis, nowMillis);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
|
||||
this.scheduledFunctions[timeoutKey] = {
|
||||
runAtMillis: this.nowMillis + millis,
|
||||
funcToCall: funcToCall,
|
||||
recurring: recurring,
|
||||
timeoutKey: timeoutKey,
|
||||
millis: millis
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @namespace
|
||||
*/
|
||||
jasmine.Clock = {
|
||||
defaultFakeTimer: new jasmine.FakeTimer(),
|
||||
|
||||
reset: function() {
|
||||
jasmine.Clock.assertInstalled();
|
||||
jasmine.Clock.defaultFakeTimer.reset();
|
||||
},
|
||||
|
||||
tick: function(millis) {
|
||||
jasmine.Clock.assertInstalled();
|
||||
jasmine.Clock.defaultFakeTimer.tick(millis);
|
||||
},
|
||||
|
||||
runFunctionsWithinRange: function(oldMillis, nowMillis) {
|
||||
jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
|
||||
},
|
||||
|
||||
scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
|
||||
jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
|
||||
},
|
||||
|
||||
useMock: function() {
|
||||
var spec = jasmine.getEnv().currentSpec;
|
||||
spec.after(jasmine.Clock.uninstallMock);
|
||||
|
||||
jasmine.Clock.installMock();
|
||||
},
|
||||
|
||||
installMock: function() {
|
||||
jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
|
||||
},
|
||||
|
||||
uninstallMock: function() {
|
||||
jasmine.Clock.assertInstalled();
|
||||
jasmine.Clock.installed = jasmine.Clock.real;
|
||||
},
|
||||
|
||||
real: {
|
||||
setTimeout: window.setTimeout,
|
||||
clearTimeout: window.clearTimeout,
|
||||
setInterval: window.setInterval,
|
||||
clearInterval: window.clearInterval
|
||||
},
|
||||
|
||||
assertInstalled: function() {
|
||||
if (jasmine.Clock.installed != jasmine.Clock.defaultFakeTimer) {
|
||||
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
|
||||
}
|
||||
},
|
||||
|
||||
installed: null
|
||||
};
|
||||
jasmine.Clock.installed = jasmine.Clock.real;
|
||||
|
||||
//else for IE support
|
||||
window.setTimeout = function(funcToCall, millis) {
|
||||
if (jasmine.Clock.installed.setTimeout.apply) {
|
||||
return jasmine.Clock.installed.setTimeout.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.setTimeout(funcToCall, millis);
|
||||
}
|
||||
};
|
||||
|
||||
window.setInterval = function(funcToCall, millis) {
|
||||
if (jasmine.Clock.installed.setInterval.apply) {
|
||||
return jasmine.Clock.installed.setInterval.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.setInterval(funcToCall, millis);
|
||||
}
|
||||
};
|
||||
|
||||
window.clearTimeout = function(timeoutKey) {
|
||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
||||
return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.clearTimeout(timeoutKey);
|
||||
}
|
||||
};
|
||||
|
||||
window.clearInterval = function(timeoutKey) {
|
||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
||||
return jasmine.Clock.installed.clearInterval.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.clearInterval(timeoutKey);
|
||||
}
|
||||
};
|
||||
|
||||
// Mock setTimeout, clearTimeout
|
||||
// Contributed by Pivotal Computer Systems, www.pivotalsf.com
|
||||
|
||||
jasmine.FakeTimer = function() {
|
||||
this.reset();
|
||||
|
||||
var self = this;
|
||||
self.setTimeout = function(funcToCall, millis) {
|
||||
self.timeoutsMade++;
|
||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
|
||||
return self.timeoutsMade;
|
||||
};
|
||||
|
||||
self.setInterval = function(funcToCall, millis) {
|
||||
self.timeoutsMade++;
|
||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
|
||||
return self.timeoutsMade;
|
||||
};
|
||||
|
||||
self.clearTimeout = function(timeoutKey) {
|
||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
||||
};
|
||||
|
||||
self.clearInterval = function(timeoutKey) {
|
||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.reset = function() {
|
||||
this.timeoutsMade = 0;
|
||||
this.scheduledFunctions = {};
|
||||
this.nowMillis = 0;
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.tick = function(millis) {
|
||||
var oldMillis = this.nowMillis;
|
||||
var newMillis = oldMillis + millis;
|
||||
this.runFunctionsWithinRange(oldMillis, newMillis);
|
||||
this.nowMillis = newMillis;
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
|
||||
var scheduledFunc;
|
||||
var funcsToRun = [];
|
||||
for (var timeoutKey in this.scheduledFunctions) {
|
||||
scheduledFunc = this.scheduledFunctions[timeoutKey];
|
||||
if (scheduledFunc != jasmine.undefined &&
|
||||
scheduledFunc.runAtMillis >= oldMillis &&
|
||||
scheduledFunc.runAtMillis <= nowMillis) {
|
||||
funcsToRun.push(scheduledFunc);
|
||||
this.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (funcsToRun.length > 0) {
|
||||
funcsToRun.sort(function(a, b) {
|
||||
return a.runAtMillis - b.runAtMillis;
|
||||
});
|
||||
for (var i = 0; i < funcsToRun.length; ++i) {
|
||||
try {
|
||||
var funcToRun = funcsToRun[i];
|
||||
this.nowMillis = funcToRun.runAtMillis;
|
||||
funcToRun.funcToCall();
|
||||
if (funcToRun.recurring) {
|
||||
this.scheduleFunction(funcToRun.timeoutKey,
|
||||
funcToRun.funcToCall,
|
||||
funcToRun.millis,
|
||||
true);
|
||||
}
|
||||
} catch(e) {
|
||||
}
|
||||
}
|
||||
this.runFunctionsWithinRange(oldMillis, nowMillis);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
|
||||
this.scheduledFunctions[timeoutKey] = {
|
||||
runAtMillis: this.nowMillis + millis,
|
||||
funcToCall: funcToCall,
|
||||
recurring: recurring,
|
||||
timeoutKey: timeoutKey,
|
||||
millis: millis
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @namespace
|
||||
*/
|
||||
jasmine.Clock = {
|
||||
defaultFakeTimer: new jasmine.FakeTimer(),
|
||||
|
||||
reset: function() {
|
||||
jasmine.Clock.assertInstalled();
|
||||
jasmine.Clock.defaultFakeTimer.reset();
|
||||
},
|
||||
|
||||
tick: function(millis) {
|
||||
jasmine.Clock.assertInstalled();
|
||||
jasmine.Clock.defaultFakeTimer.tick(millis);
|
||||
},
|
||||
|
||||
runFunctionsWithinRange: function(oldMillis, nowMillis) {
|
||||
jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
|
||||
},
|
||||
|
||||
scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
|
||||
jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
|
||||
},
|
||||
|
||||
useMock: function() {
|
||||
var spec = jasmine.getEnv().currentSpec;
|
||||
spec.after(jasmine.Clock.uninstallMock);
|
||||
|
||||
jasmine.Clock.installMock();
|
||||
},
|
||||
|
||||
installMock: function() {
|
||||
jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
|
||||
},
|
||||
|
||||
uninstallMock: function() {
|
||||
jasmine.Clock.assertInstalled();
|
||||
jasmine.Clock.installed = jasmine.Clock.real;
|
||||
},
|
||||
|
||||
real: {
|
||||
setTimeout: window.setTimeout,
|
||||
clearTimeout: window.clearTimeout,
|
||||
setInterval: window.setInterval,
|
||||
clearInterval: window.clearInterval
|
||||
},
|
||||
|
||||
assertInstalled: function() {
|
||||
if (jasmine.Clock.installed != jasmine.Clock.defaultFakeTimer) {
|
||||
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
|
||||
}
|
||||
},
|
||||
|
||||
installed: null
|
||||
};
|
||||
jasmine.Clock.installed = jasmine.Clock.real;
|
||||
|
||||
//else for IE support
|
||||
window.setTimeout = function(funcToCall, millis) {
|
||||
if (jasmine.Clock.installed.setTimeout.apply) {
|
||||
return jasmine.Clock.installed.setTimeout.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.setTimeout(funcToCall, millis);
|
||||
}
|
||||
};
|
||||
|
||||
window.setInterval = function(funcToCall, millis) {
|
||||
if (jasmine.Clock.installed.setInterval.apply) {
|
||||
return jasmine.Clock.installed.setInterval.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.setInterval(funcToCall, millis);
|
||||
}
|
||||
};
|
||||
|
||||
window.clearTimeout = function(timeoutKey) {
|
||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
||||
return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.clearTimeout(timeoutKey);
|
||||
}
|
||||
};
|
||||
|
||||
window.clearInterval = function(timeoutKey) {
|
||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
||||
return jasmine.Clock.installed.clearInterval.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.clearInterval(timeoutKey);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
jasmine.version_= {
|
||||
"major": 0,
|
||||
"minor": 10,
|
||||
"build": 2,
|
||||
"revision": 1268969696
|
||||
"build": 4,
|
||||
"revision": 1275748595
|
||||
};
|
||||
104
lib/jasmine.css
104
lib/jasmine.css
@@ -3,8 +3,40 @@ body {
|
||||
}
|
||||
|
||||
|
||||
body .run_spec {
|
||||
float:right;
|
||||
.jasmine_reporter a:visited, .jasmine_reporter a {
|
||||
color: #303;
|
||||
}
|
||||
|
||||
.jasmine_reporter a:hover, .jasmine_reporter a:active {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.run_spec {
|
||||
float:right;
|
||||
padding-right: 5px;
|
||||
font-size: .8em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.jasmine_reporter {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.banner {
|
||||
color: #303;
|
||||
background-color: #fef;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
float: left;
|
||||
font-size: 1.1em;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.logo .version {
|
||||
font-size: .6em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.runner.running {
|
||||
@@ -12,24 +44,26 @@ body .run_spec {
|
||||
}
|
||||
|
||||
|
||||
|
||||
.runner {
|
||||
border: 1px solid gray;
|
||||
margin: 5px;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
.options {
|
||||
text-align: right;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.suite {
|
||||
border: 1px outset gray;
|
||||
margin: 5px;
|
||||
margin: 5px 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.suite .suite {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.suite.passed {
|
||||
background-color: #cfc;
|
||||
background-color: #dfd;
|
||||
}
|
||||
|
||||
.suite.failed {
|
||||
@@ -38,22 +72,51 @@ body .run_spec {
|
||||
|
||||
.spec {
|
||||
margin: 5px;
|
||||
padding-left: 1em;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.spec.failed, .spec.passed, .spec.skipped {
|
||||
padding-bottom: 5px;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.spec.failed {
|
||||
background-color: #fbb;
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
.spec.passed {
|
||||
background-color: #bfb;
|
||||
border-color: green;
|
||||
}
|
||||
|
||||
.spec.skipped {
|
||||
background-color: #bbb;
|
||||
}
|
||||
|
||||
.messages {
|
||||
border-left: 1px dashed gray;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.passed {
|
||||
background-color: #cfc;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.failed {
|
||||
background-color: #fdd;
|
||||
background-color: #fbb;
|
||||
}
|
||||
|
||||
.skipped {
|
||||
color: #777;
|
||||
background-color: #eee;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*.resultMessage {*/
|
||||
/*white-space: pre;*/
|
||||
/*}*/
|
||||
@@ -72,15 +135,32 @@ body .run_spec {
|
||||
white-space: pre;
|
||||
font-size: .8em;
|
||||
margin-left: 10px;
|
||||
height: 5em;
|
||||
max-height: 5em;
|
||||
overflow: auto;
|
||||
border: 1px inset red;
|
||||
padding: 1em;
|
||||
background: #eef;
|
||||
}
|
||||
|
||||
.finished-at {
|
||||
padding-left: 1em;
|
||||
font-size: .6em;
|
||||
}
|
||||
|
||||
.show-passed .passed,
|
||||
.show-skipped .skipped {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
#jasmine_content {
|
||||
position:fixed;
|
||||
right: 100%;
|
||||
}
|
||||
|
||||
.runner {
|
||||
border: 1px solid gray;
|
||||
display: block;
|
||||
margin: 5px 0;
|
||||
padding: 2px 0 2px 10px;
|
||||
}
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
// yes, really keep this here to keep us honest, but only for jasmine's own runner! [xw]
|
||||
undefined = "diz be undefined yo";
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript" src="../src/base.js"></script>
|
||||
<script type="text/javascript" src="../src/util.js"></script>
|
||||
<script type="text/javascript" src="../src/Env.js"></script>
|
||||
<script type="text/javascript" src="../src/Reporter.js"></script>
|
||||
<script type="text/javascript" src="../src/Block.js"></script>
|
||||
|
||||
|
||||
<script type="text/javascript" src="../src/JsApiReporter.js"></script>
|
||||
<script type="text/javascript" src="../src/Matchers.js"></script>
|
||||
<script type="text/javascript" src="../src/mock-timeout.js"></script>
|
||||
@@ -28,35 +28,33 @@
|
||||
<script type="text/javascript" src="../src/Suite.js"></script>
|
||||
<script type="text/javascript" src="../src/WaitsBlock.js"></script>
|
||||
<script type="text/javascript" src="../src/WaitsForBlock.js"></script>
|
||||
|
||||
|
||||
<script type="text/javascript" src="../lib/TrivialReporter.js"></script>
|
||||
<script type="text/javascript" src="../lib/consolex.js"></script>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
var suites = [
|
||||
'suites/CustomMatchersSpec.js',
|
||||
'suites/EnvSpec.js',
|
||||
'suites/ExceptionsSpec.js',
|
||||
'suites/JsApiReporterSpec.js',
|
||||
'suites/MatchersSpec.js',
|
||||
'suites/MultiReporterSpec.js',
|
||||
'suites/NestedResultsSpec.js',
|
||||
'suites/PrettyPrintSpec.js',
|
||||
'suites/ReporterSpec.js',
|
||||
'suites/RunnerSpec.js',
|
||||
'suites/QueueSpec.js',
|
||||
'suites/SpecSpec.js',
|
||||
'suites/SpecRunningSpec.js',
|
||||
'suites/SpySpec.js',
|
||||
'suites/SuiteSpec.js',
|
||||
'suites/TrivialReporterSpec.js',
|
||||
];
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
jasmine.include(suites[i], true);
|
||||
}
|
||||
|
||||
<script type="text/javascript" src="suites/CustomMatchersSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/EnvSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/ExceptionsSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/JsApiReporterSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/MatchersSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/MultiReporterSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/NestedResultsSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/PrettyPrintSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/ReporterSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/RunnerSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/QueueSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/SpecSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/SpecRunningSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/SpySpec.js"></script>
|
||||
<script type="text/javascript" src="suites/SuiteSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/TrivialReporterSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/WaitsForBlockSpec.js"></script>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
var jasmineEnv = jasmine.getEnv();
|
||||
jasmineEnv.updateInterval = 1000;
|
||||
|
||||
|
||||
@@ -57,6 +57,23 @@ describe("jasmine.Env", function() {
|
||||
"revision": 8
|
||||
});
|
||||
});
|
||||
|
||||
describe("versionString", function() {
|
||||
it("should return a stringified version number", function() {
|
||||
jasmine.version_ = {
|
||||
"major": 1,
|
||||
"minor": 9,
|
||||
"build": 7,
|
||||
"revision": 8
|
||||
};
|
||||
expect(env.versionString()).toEqual("1.9.7 revision 8");
|
||||
});
|
||||
|
||||
it("should return a nice string when version is unknown", function() {
|
||||
jasmine.version_ = null;
|
||||
expect(env.versionString()).toEqual("version unknown");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should allow reporters to be registered", function() {
|
||||
@@ -138,4 +155,4 @@ describe("jasmine.Env", function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -861,7 +861,7 @@ describe("jasmine spec running", function () {
|
||||
expect(suiteResults.getItems()[2].getItems()[0].passed()).toEqual(true, "testAfterExecutesSafely 3rd suite spec should pass");
|
||||
});
|
||||
|
||||
it("testNestedDescribes", function() {
|
||||
it("should permit nested describes", function() {
|
||||
var actions = [];
|
||||
|
||||
env.beforeEach(function () {
|
||||
@@ -953,6 +953,63 @@ describe("jasmine spec running", function () {
|
||||
expect(actions).toEqual(expected);
|
||||
});
|
||||
|
||||
it("should run multiple befores and afters in the order they are declared", function() {
|
||||
var actions = [];
|
||||
|
||||
env.beforeEach(function () {
|
||||
actions.push('runner beforeEach1');
|
||||
});
|
||||
|
||||
env.afterEach(function () {
|
||||
actions.push('runner afterEach1');
|
||||
});
|
||||
|
||||
env.beforeEach(function () {
|
||||
actions.push('runner beforeEach2');
|
||||
});
|
||||
|
||||
env.afterEach(function () {
|
||||
actions.push('runner afterEach2');
|
||||
});
|
||||
|
||||
env.describe('Something', function() {
|
||||
env.beforeEach(function() {
|
||||
actions.push('beforeEach1');
|
||||
});
|
||||
|
||||
env.afterEach(function() {
|
||||
actions.push('afterEach1');
|
||||
});
|
||||
|
||||
env.beforeEach(function() {
|
||||
actions.push('beforeEach2');
|
||||
});
|
||||
|
||||
env.afterEach(function() {
|
||||
actions.push('afterEach2');
|
||||
});
|
||||
|
||||
env.it('does it 1', function() {
|
||||
actions.push('outer it 1');
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
|
||||
var expected = [
|
||||
"runner beforeEach1",
|
||||
"runner beforeEach2",
|
||||
"beforeEach1",
|
||||
"beforeEach2",
|
||||
"outer it 1",
|
||||
"afterEach2",
|
||||
"afterEach1",
|
||||
"runner afterEach2",
|
||||
"runner afterEach1"
|
||||
];
|
||||
expect(actions).toEqual(expected);
|
||||
});
|
||||
|
||||
it("builds up nested names", function() {
|
||||
var nestedSpec;
|
||||
env.describe('Test Subject', function() {
|
||||
@@ -1083,4 +1140,56 @@ describe("jasmine spec running", function () {
|
||||
expect(exceptionMessage).toEqual('explodes function should not have been called');
|
||||
});
|
||||
|
||||
it("should recover gracefully when there are errors in describe functions", function() {
|
||||
var specs = [];
|
||||
var superSimpleReporter = new jasmine.Reporter();
|
||||
superSimpleReporter.reportSpecResults = function(spec) {
|
||||
specs.push("Spec: " + spec.getFullName());
|
||||
var results = spec.results().getItems();
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
var result = results[i];
|
||||
specs.push("Result: " + result);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
env.describe("outer1", function() {
|
||||
env.describe("inner1", function() {
|
||||
env.it("should thingy", function() {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
|
||||
throw new Error("fake error");
|
||||
});
|
||||
|
||||
env.describe("inner2", function() {
|
||||
env.it("should other thingy", function() {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
env.describe("outer2", function() {
|
||||
env.it("should xxx", function() {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
env.addReporter(superSimpleReporter);
|
||||
env.execute();
|
||||
|
||||
expect(specs.join('')).toMatch(new RegExp(
|
||||
'Spec: outer1 inner1 should thingy.' +
|
||||
'Result: Passed.' +
|
||||
'Spec: outer1 encountered a declaration exception.' +
|
||||
'Result: Error: fake error.*' +
|
||||
'Spec: outer1 inner2 should other thingy.' +
|
||||
'Result: Passed.' +
|
||||
'Spec: outer2 should xxx.' +
|
||||
'Result: Passed.'
|
||||
));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -14,6 +14,20 @@ describe("TrivialReporter", function() {
|
||||
};
|
||||
}
|
||||
|
||||
function findElements(divs, withClass) {
|
||||
var els = [];
|
||||
for (var i = 0; i < divs.length; i++) {
|
||||
if (divs[i].className == withClass) els.push(divs[i]);
|
||||
}
|
||||
return els;
|
||||
}
|
||||
|
||||
function findElement(divs, withClass) {
|
||||
var els = findElements(divs, withClass);
|
||||
if (els.length > 0) return els[0];
|
||||
throw new Error("couldn't find div with class " + withClass);
|
||||
}
|
||||
|
||||
it("should run only specs beginning with spec parameter", function() {
|
||||
var trivialReporter = new jasmine.TrivialReporter({ location: {search: "?spec=run%20this"} });
|
||||
expect(trivialReporter.specFilter(fakeSpec("run this"))).toBeTruthy();
|
||||
@@ -24,14 +38,15 @@ describe("TrivialReporter", function() {
|
||||
it("should display empty divs for every suite when the runner is starting", function() {
|
||||
var trivialReporter = new jasmine.TrivialReporter({ body: body });
|
||||
trivialReporter.reportRunnerStarting({
|
||||
env: new jasmine.Env(),
|
||||
suites: function() {
|
||||
return [ new jasmine.Suite({}, "suite 1", null, null) ];
|
||||
}
|
||||
});
|
||||
|
||||
var divs = body.getElementsByTagName("div");
|
||||
expect(divs.length).toEqual(2);
|
||||
expect(divs[1].innerHTML).toContain("suite 1");
|
||||
var divs = findElements(body.getElementsByTagName("div"), "suite");
|
||||
expect(divs.length).toEqual(1);
|
||||
expect(divs[0].innerHTML).toContain("suite 1");
|
||||
});
|
||||
|
||||
describe('Matcher reporting', function () {
|
||||
@@ -104,6 +119,7 @@ describe("TrivialReporter", function() {
|
||||
|
||||
trivialReporter = new jasmine.TrivialReporter({ body: body });
|
||||
trivialReporter.reportRunnerStarting({
|
||||
env: new jasmine.Env(),
|
||||
suites: function() {
|
||||
return [ new jasmine.Suite({}, "suite 1", null, null) ];
|
||||
}
|
||||
@@ -120,10 +136,11 @@ describe("TrivialReporter", function() {
|
||||
trivialReporter.reportSpecResults(spec);
|
||||
|
||||
var divs = body.getElementsByTagName("div");
|
||||
expect(divs[3].innerHTML).toEqual("Expected 'a' to be null, but it was not");
|
||||
var errorDiv = findElement(divs, 'resultMessage fail');
|
||||
expect(errorDiv.innerHTML).toEqual("Expected 'a' to be null, but it was not");
|
||||
});
|
||||
|
||||
it("should add the failure message to the DOM (non-toEquals matchers)", function() {
|
||||
it("should add the failure message to the DOM (non-toEquals matchers) html escaping", function() {
|
||||
expectationResult = new jasmine.ExpectationResult({
|
||||
matcherName: "toBeNull", passed: false, message: "Expected '1 < 2' to <b>e null, & it was not"
|
||||
});
|
||||
@@ -133,7 +150,8 @@ describe("TrivialReporter", function() {
|
||||
trivialReporter.reportSpecResults(spec);
|
||||
|
||||
var divs = body.getElementsByTagName("div");
|
||||
expect(divs[3].innerHTML).toEqual("Expected '1 < 2' to <b>e null, & it was not");
|
||||
var errorDiv = findElement(divs, 'resultMessage fail');
|
||||
expect(errorDiv.innerHTML).toEqual("Expected '1 < 2' to <b>e null, & it was not");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
88
spec/suites/WaitsForBlockSpec.js
Normal file
88
spec/suites/WaitsForBlockSpec.js
Normal file
@@ -0,0 +1,88 @@
|
||||
describe('WaitsForBlock', function () {
|
||||
var env, suite, timeout, spec, message, onComplete, fakeTimer;
|
||||
beforeEach(function() {
|
||||
env = new jasmine.Env();
|
||||
env.updateInterval = 0;
|
||||
suite = new jasmine.Suite(env, 'suite 1');
|
||||
timeout = 1000;
|
||||
spec = new jasmine.Spec(env, suite);
|
||||
message = "some error message";
|
||||
onComplete = jasmine.createSpy("onComplete");
|
||||
});
|
||||
|
||||
it('onComplete should be called if the latchFunction returns true', function () {
|
||||
var latchFunction = function() {
|
||||
return true;
|
||||
};
|
||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
||||
expect(onComplete).wasNotCalled();
|
||||
block.execute(onComplete);
|
||||
expect(onComplete).wasCalled();
|
||||
});
|
||||
|
||||
it('latchFunction should run in same scope as spec', function () {
|
||||
var result;
|
||||
var latchFunction = function() {
|
||||
result = this.scopedValue;
|
||||
};
|
||||
spec.scopedValue = 'foo';
|
||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
||||
block.execute(onComplete);
|
||||
expect(result).toEqual('foo');
|
||||
});
|
||||
|
||||
it('should fail spec and call onComplete if there is an error in the latchFunction', function() {
|
||||
var latchFunction = jasmine.createSpy('latchFunction').andThrow('some error');
|
||||
spyOn(spec, 'fail');
|
||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
||||
block.execute(onComplete);
|
||||
expect(spec.fail).wasCalledWith('some error');
|
||||
expect(onComplete).wasCalled();
|
||||
});
|
||||
|
||||
describe("if latchFunction returns false", function() {
|
||||
var latchFunction, fakeTimer;
|
||||
beforeEach(function() {
|
||||
latchFunction = jasmine.createSpy('latchFunction').andReturn(false);
|
||||
fakeTimer = new jasmine.FakeTimer();
|
||||
env.setTimeout = fakeTimer.setTimeout;
|
||||
env.clearTimeout = fakeTimer.clearTimeout;
|
||||
env.setInterval = fakeTimer.setInterval;
|
||||
env.clearInterval = fakeTimer.clearInterval;
|
||||
});
|
||||
|
||||
it('latchFunction should be retried after 100 ms', function () {
|
||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
||||
expect(latchFunction).wasNotCalled();
|
||||
block.execute(onComplete);
|
||||
expect(latchFunction.callCount).toEqual(1);
|
||||
fakeTimer.tick(50);
|
||||
expect(latchFunction.callCount).toEqual(1);
|
||||
fakeTimer.tick(50);
|
||||
expect(latchFunction.callCount).toEqual(2);
|
||||
});
|
||||
|
||||
it('onComplete should be called if latchFunction returns true before timeout', function () {
|
||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
||||
expect(onComplete).wasNotCalled();
|
||||
block.execute(onComplete);
|
||||
expect(onComplete).wasNotCalled();
|
||||
latchFunction.andReturn(true);
|
||||
fakeTimer.tick(100);
|
||||
expect(onComplete).wasCalled();
|
||||
});
|
||||
|
||||
it('spec should fail with the passed message if the timeout is reached (and not call onComplete)', function () {
|
||||
spyOn(spec, 'fail');
|
||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
||||
block.execute(onComplete);
|
||||
expect(spec.fail).wasNotCalled();
|
||||
fakeTimer.tick(timeout);
|
||||
expect(spec.fail).wasCalled();
|
||||
var failMessage = spec.fail.mostRecentCall.args[0].message;
|
||||
expect(failMessage).toMatch(message);
|
||||
expect(onComplete).wasNotCalled();
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
25
src/Env.js
25
src/Env.js
@@ -46,6 +46,18 @@ jasmine.Env.prototype.version = function () {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns string containing jasmine version build info, if set.
|
||||
*/
|
||||
jasmine.Env.prototype.versionString = function() {
|
||||
if (jasmine.version_) {
|
||||
var version = this.version();
|
||||
return version.major + "." + version.minor + "." + version.build + " revision " + version.revision;
|
||||
} else {
|
||||
return "version unknown";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns a sequential integer starting at 0
|
||||
*/
|
||||
@@ -84,10 +96,21 @@ jasmine.Env.prototype.describe = function(description, specDefinitions) {
|
||||
|
||||
this.currentSuite = suite;
|
||||
|
||||
specDefinitions.call(suite);
|
||||
var declarationError = null;
|
||||
try {
|
||||
specDefinitions.call(suite);
|
||||
} catch(e) {
|
||||
declarationError = e;
|
||||
}
|
||||
|
||||
this.currentSuite = parentSuite;
|
||||
|
||||
if (declarationError) {
|
||||
this.it("encountered a declaration exception", function() {
|
||||
throw declarationError;
|
||||
});
|
||||
}
|
||||
|
||||
return suite;
|
||||
};
|
||||
|
||||
|
||||
@@ -25,12 +25,12 @@ jasmine.Runner.prototype.execute = function() {
|
||||
|
||||
jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
|
||||
beforeEachFunction.typeName = 'beforeEach';
|
||||
this.before_.push(beforeEachFunction);
|
||||
this.before_.splice(0,0,beforeEachFunction);
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
|
||||
afterEachFunction.typeName = 'afterEach';
|
||||
this.after_.push(afterEachFunction);
|
||||
this.after_.splice(0,0,afterEachFunction);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -37,12 +37,12 @@ jasmine.Suite.prototype.finish = function(onComplete) {
|
||||
|
||||
jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
|
||||
beforeEachFunction.typeName = 'beforeEach';
|
||||
this.before_.push(beforeEachFunction);
|
||||
this.before_.unshift(beforeEachFunction);
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
|
||||
afterEachFunction.typeName = 'afterEach';
|
||||
this.after_.push(afterEachFunction);
|
||||
this.after_.unshift(afterEachFunction);
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.results = function() {
|
||||
|
||||
@@ -30,7 +30,6 @@ jasmine.WaitsForBlock.prototype.execute = function (onComplete) {
|
||||
name: 'timeout',
|
||||
message: message
|
||||
});
|
||||
self.spec._next();
|
||||
} else {
|
||||
self.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
|
||||
self.env.setTimeout(function () { self.execute(onComplete); }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
|
||||
|
||||
11
src/base.js
11
src/base.js
@@ -13,7 +13,7 @@ jasmine.unimplementedMethod_ = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code is just
|
||||
* Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
|
||||
* a plain old variable and may be redefined by somebody else.
|
||||
*
|
||||
* @private
|
||||
@@ -57,6 +57,10 @@ jasmine.MessageResult = function(text) {
|
||||
this.trace = new Error(); // todo: test better
|
||||
};
|
||||
|
||||
jasmine.MessageResult.prototype.toString = function() {
|
||||
return this.text;
|
||||
};
|
||||
|
||||
jasmine.ExpectationResult = function(params) {
|
||||
this.type = 'ExpectationResult';
|
||||
this.matcherName = params.matcherName;
|
||||
@@ -71,6 +75,10 @@ jasmine.ExpectationResult = function(params) {
|
||||
this.trace = this.passed_ ? '' : new Error(this.message);
|
||||
};
|
||||
|
||||
jasmine.ExpectationResult.prototype.toString = function () {
|
||||
return this.message;
|
||||
};
|
||||
|
||||
jasmine.ExpectationResult.prototype.passed = function () {
|
||||
return this.passed_;
|
||||
};
|
||||
@@ -558,6 +566,7 @@ jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
|
||||
*
|
||||
* @param {String} url path to the file to include
|
||||
* @param {Boolean} opt_global
|
||||
* @deprecated We suggest you use a different method of including JS source files. <code>jasmine.include</code> will be removed soon.
|
||||
*/
|
||||
jasmine.include = function(url, opt_global) {
|
||||
if (opt_global) {
|
||||
|
||||
@@ -1,177 +1,177 @@
|
||||
// Mock setTimeout, clearTimeout
|
||||
// Contributed by Pivotal Computer Systems, www.pivotalsf.com
|
||||
|
||||
jasmine.FakeTimer = function() {
|
||||
this.reset();
|
||||
|
||||
var self = this;
|
||||
self.setTimeout = function(funcToCall, millis) {
|
||||
self.timeoutsMade++;
|
||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
|
||||
return self.timeoutsMade;
|
||||
};
|
||||
|
||||
self.setInterval = function(funcToCall, millis) {
|
||||
self.timeoutsMade++;
|
||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
|
||||
return self.timeoutsMade;
|
||||
};
|
||||
|
||||
self.clearTimeout = function(timeoutKey) {
|
||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
||||
};
|
||||
|
||||
self.clearInterval = function(timeoutKey) {
|
||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.reset = function() {
|
||||
this.timeoutsMade = 0;
|
||||
this.scheduledFunctions = {};
|
||||
this.nowMillis = 0;
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.tick = function(millis) {
|
||||
var oldMillis = this.nowMillis;
|
||||
var newMillis = oldMillis + millis;
|
||||
this.runFunctionsWithinRange(oldMillis, newMillis);
|
||||
this.nowMillis = newMillis;
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
|
||||
var scheduledFunc;
|
||||
var funcsToRun = [];
|
||||
for (var timeoutKey in this.scheduledFunctions) {
|
||||
scheduledFunc = this.scheduledFunctions[timeoutKey];
|
||||
if (scheduledFunc != jasmine.undefined &&
|
||||
scheduledFunc.runAtMillis >= oldMillis &&
|
||||
scheduledFunc.runAtMillis <= nowMillis) {
|
||||
funcsToRun.push(scheduledFunc);
|
||||
this.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (funcsToRun.length > 0) {
|
||||
funcsToRun.sort(function(a, b) {
|
||||
return a.runAtMillis - b.runAtMillis;
|
||||
});
|
||||
for (var i = 0; i < funcsToRun.length; ++i) {
|
||||
try {
|
||||
var funcToRun = funcsToRun[i];
|
||||
this.nowMillis = funcToRun.runAtMillis;
|
||||
funcToRun.funcToCall();
|
||||
if (funcToRun.recurring) {
|
||||
this.scheduleFunction(funcToRun.timeoutKey,
|
||||
funcToRun.funcToCall,
|
||||
funcToRun.millis,
|
||||
true);
|
||||
}
|
||||
} catch(e) {
|
||||
}
|
||||
}
|
||||
this.runFunctionsWithinRange(oldMillis, nowMillis);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
|
||||
this.scheduledFunctions[timeoutKey] = {
|
||||
runAtMillis: this.nowMillis + millis,
|
||||
funcToCall: funcToCall,
|
||||
recurring: recurring,
|
||||
timeoutKey: timeoutKey,
|
||||
millis: millis
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @namespace
|
||||
*/
|
||||
jasmine.Clock = {
|
||||
defaultFakeTimer: new jasmine.FakeTimer(),
|
||||
|
||||
reset: function() {
|
||||
jasmine.Clock.assertInstalled();
|
||||
jasmine.Clock.defaultFakeTimer.reset();
|
||||
},
|
||||
|
||||
tick: function(millis) {
|
||||
jasmine.Clock.assertInstalled();
|
||||
jasmine.Clock.defaultFakeTimer.tick(millis);
|
||||
},
|
||||
|
||||
runFunctionsWithinRange: function(oldMillis, nowMillis) {
|
||||
jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
|
||||
},
|
||||
|
||||
scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
|
||||
jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
|
||||
},
|
||||
|
||||
useMock: function() {
|
||||
var spec = jasmine.getEnv().currentSpec;
|
||||
spec.after(jasmine.Clock.uninstallMock);
|
||||
|
||||
jasmine.Clock.installMock();
|
||||
},
|
||||
|
||||
installMock: function() {
|
||||
jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
|
||||
},
|
||||
|
||||
uninstallMock: function() {
|
||||
jasmine.Clock.assertInstalled();
|
||||
jasmine.Clock.installed = jasmine.Clock.real;
|
||||
},
|
||||
|
||||
real: {
|
||||
setTimeout: window.setTimeout,
|
||||
clearTimeout: window.clearTimeout,
|
||||
setInterval: window.setInterval,
|
||||
clearInterval: window.clearInterval
|
||||
},
|
||||
|
||||
assertInstalled: function() {
|
||||
if (jasmine.Clock.installed != jasmine.Clock.defaultFakeTimer) {
|
||||
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
|
||||
}
|
||||
},
|
||||
|
||||
installed: null
|
||||
};
|
||||
jasmine.Clock.installed = jasmine.Clock.real;
|
||||
|
||||
//else for IE support
|
||||
window.setTimeout = function(funcToCall, millis) {
|
||||
if (jasmine.Clock.installed.setTimeout.apply) {
|
||||
return jasmine.Clock.installed.setTimeout.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.setTimeout(funcToCall, millis);
|
||||
}
|
||||
};
|
||||
|
||||
window.setInterval = function(funcToCall, millis) {
|
||||
if (jasmine.Clock.installed.setInterval.apply) {
|
||||
return jasmine.Clock.installed.setInterval.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.setInterval(funcToCall, millis);
|
||||
}
|
||||
};
|
||||
|
||||
window.clearTimeout = function(timeoutKey) {
|
||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
||||
return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.clearTimeout(timeoutKey);
|
||||
}
|
||||
};
|
||||
|
||||
window.clearInterval = function(timeoutKey) {
|
||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
||||
return jasmine.Clock.installed.clearInterval.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.clearInterval(timeoutKey);
|
||||
}
|
||||
};
|
||||
|
||||
// Mock setTimeout, clearTimeout
|
||||
// Contributed by Pivotal Computer Systems, www.pivotalsf.com
|
||||
|
||||
jasmine.FakeTimer = function() {
|
||||
this.reset();
|
||||
|
||||
var self = this;
|
||||
self.setTimeout = function(funcToCall, millis) {
|
||||
self.timeoutsMade++;
|
||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
|
||||
return self.timeoutsMade;
|
||||
};
|
||||
|
||||
self.setInterval = function(funcToCall, millis) {
|
||||
self.timeoutsMade++;
|
||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
|
||||
return self.timeoutsMade;
|
||||
};
|
||||
|
||||
self.clearTimeout = function(timeoutKey) {
|
||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
||||
};
|
||||
|
||||
self.clearInterval = function(timeoutKey) {
|
||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.reset = function() {
|
||||
this.timeoutsMade = 0;
|
||||
this.scheduledFunctions = {};
|
||||
this.nowMillis = 0;
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.tick = function(millis) {
|
||||
var oldMillis = this.nowMillis;
|
||||
var newMillis = oldMillis + millis;
|
||||
this.runFunctionsWithinRange(oldMillis, newMillis);
|
||||
this.nowMillis = newMillis;
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
|
||||
var scheduledFunc;
|
||||
var funcsToRun = [];
|
||||
for (var timeoutKey in this.scheduledFunctions) {
|
||||
scheduledFunc = this.scheduledFunctions[timeoutKey];
|
||||
if (scheduledFunc != jasmine.undefined &&
|
||||
scheduledFunc.runAtMillis >= oldMillis &&
|
||||
scheduledFunc.runAtMillis <= nowMillis) {
|
||||
funcsToRun.push(scheduledFunc);
|
||||
this.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (funcsToRun.length > 0) {
|
||||
funcsToRun.sort(function(a, b) {
|
||||
return a.runAtMillis - b.runAtMillis;
|
||||
});
|
||||
for (var i = 0; i < funcsToRun.length; ++i) {
|
||||
try {
|
||||
var funcToRun = funcsToRun[i];
|
||||
this.nowMillis = funcToRun.runAtMillis;
|
||||
funcToRun.funcToCall();
|
||||
if (funcToRun.recurring) {
|
||||
this.scheduleFunction(funcToRun.timeoutKey,
|
||||
funcToRun.funcToCall,
|
||||
funcToRun.millis,
|
||||
true);
|
||||
}
|
||||
} catch(e) {
|
||||
}
|
||||
}
|
||||
this.runFunctionsWithinRange(oldMillis, nowMillis);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
|
||||
this.scheduledFunctions[timeoutKey] = {
|
||||
runAtMillis: this.nowMillis + millis,
|
||||
funcToCall: funcToCall,
|
||||
recurring: recurring,
|
||||
timeoutKey: timeoutKey,
|
||||
millis: millis
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @namespace
|
||||
*/
|
||||
jasmine.Clock = {
|
||||
defaultFakeTimer: new jasmine.FakeTimer(),
|
||||
|
||||
reset: function() {
|
||||
jasmine.Clock.assertInstalled();
|
||||
jasmine.Clock.defaultFakeTimer.reset();
|
||||
},
|
||||
|
||||
tick: function(millis) {
|
||||
jasmine.Clock.assertInstalled();
|
||||
jasmine.Clock.defaultFakeTimer.tick(millis);
|
||||
},
|
||||
|
||||
runFunctionsWithinRange: function(oldMillis, nowMillis) {
|
||||
jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
|
||||
},
|
||||
|
||||
scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
|
||||
jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
|
||||
},
|
||||
|
||||
useMock: function() {
|
||||
var spec = jasmine.getEnv().currentSpec;
|
||||
spec.after(jasmine.Clock.uninstallMock);
|
||||
|
||||
jasmine.Clock.installMock();
|
||||
},
|
||||
|
||||
installMock: function() {
|
||||
jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
|
||||
},
|
||||
|
||||
uninstallMock: function() {
|
||||
jasmine.Clock.assertInstalled();
|
||||
jasmine.Clock.installed = jasmine.Clock.real;
|
||||
},
|
||||
|
||||
real: {
|
||||
setTimeout: window.setTimeout,
|
||||
clearTimeout: window.clearTimeout,
|
||||
setInterval: window.setInterval,
|
||||
clearInterval: window.clearInterval
|
||||
},
|
||||
|
||||
assertInstalled: function() {
|
||||
if (jasmine.Clock.installed != jasmine.Clock.defaultFakeTimer) {
|
||||
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
|
||||
}
|
||||
},
|
||||
|
||||
installed: null
|
||||
};
|
||||
jasmine.Clock.installed = jasmine.Clock.real;
|
||||
|
||||
//else for IE support
|
||||
window.setTimeout = function(funcToCall, millis) {
|
||||
if (jasmine.Clock.installed.setTimeout.apply) {
|
||||
return jasmine.Clock.installed.setTimeout.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.setTimeout(funcToCall, millis);
|
||||
}
|
||||
};
|
||||
|
||||
window.setInterval = function(funcToCall, millis) {
|
||||
if (jasmine.Clock.installed.setInterval.apply) {
|
||||
return jasmine.Clock.installed.setInterval.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.setInterval(funcToCall, millis);
|
||||
}
|
||||
};
|
||||
|
||||
window.clearTimeout = function(timeoutKey) {
|
||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
||||
return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.clearTimeout(timeoutKey);
|
||||
}
|
||||
};
|
||||
|
||||
window.clearInterval = function(timeoutKey) {
|
||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
||||
return jasmine.Clock.installed.clearInterval.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.clearInterval(timeoutKey);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"major": 0,
|
||||
"minor": 10,
|
||||
"build": 2
|
||||
}
|
||||
"build": 4
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user