Compare commits
409 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1530ad25f9 | |||
| b2557e4ebe | |||
| 85c265e7c5 | |||
| cc36a1808b | |||
| 685344342a | |||
| a4eab045a0 | |||
| cd0346b449 | |||
| f134c6e386 | |||
| 75238bd3b1 | |||
| b8b4457b6b | |||
| b33b2d2cf1 | |||
| 3ec736f64c | |||
| e7a57606a2 | |||
| 55149310c3 | |||
| 254ebb8a03 | |||
| 762f88e3c8 | |||
| b3715075e3 | |||
| 9af81b627b | |||
| 5d44da0238 | |||
| 93952890c3 | |||
| 5182e00c66 | |||
| 676af93bea | |||
| 4d7b839473 | |||
| 89afebd86b | |||
| 31020bb51d | |||
| 17e9a038a2 | |||
| 1e01000c17 | |||
| 6562b5a3b4 | |||
| 15955df258 | |||
| 81bf4784cd | |||
| 14486f5912 | |||
| 9842c8ff81 | |||
| feb4618c31 | |||
| c6acfb3982 | |||
| ba5bd3f866 | |||
| 0331209413 | |||
| 57491a0088 | |||
| e6b6d9ca95 | |||
| bf44d4b0db | |||
| 3da73bd519 | |||
| 61c0fe781c | |||
| 766f3546bf | |||
| f6d1f7d871 | |||
| 5e843e087b | |||
| 51c0563608 | |||
| 9e3036fbf7 | |||
| dcc8b460d1 | |||
| c533b67aa5 | |||
| 7a69d64669 | |||
| ed80a0cad7 | |||
| 85351f2c1c | |||
| 1057596665 | |||
| 22065fafad | |||
| 2939aff80c | |||
| 6a0e452788 | |||
| 00296b02e0 | |||
| 8f5f6a6d27 | |||
| ed47ececa9 | |||
| 9c8180d8d0 | |||
| 6a9f74e849 | |||
| 3be2455d8c | |||
| 40b0c49d25 | |||
| 82e04c327a | |||
| 2a3376d11e | |||
| 413be6b4ca | |||
| 0539251fe6 | |||
| 1154fcaf3b | |||
| 01d842fdfd | |||
| e60f22a2e5 | |||
| e7cd6a473a | |||
| 3bdc96c00a | |||
| b9bf42c6b5 | |||
| 2d138f1cfa | |||
| e30b99e7b3 | |||
| 40272cd563 | |||
| c187adc096 | |||
| 5aa306cf66 | |||
| 462b50e84e | |||
| 46249bf515 | |||
| 03d7bfb7d4 | |||
| 11292ff83c | |||
| ab7678e713 | |||
| 6431431dfc | |||
| a2041e90a6 | |||
| ed49104fad | |||
| 803a2fb2ba | |||
| bb1928a75c | |||
| 7d5ff6985f | |||
| 841e93fc09 | |||
| 5cfb019b6b | |||
| 9f8d18b6b7 | |||
| f0574086de | |||
| 2212d755c3 | |||
| 5f10b2e623 | |||
| d8ed4156c7 | |||
| 1469f83262 | |||
| d6353a3db2 | |||
| 9a5b46fd99 | |||
| bf938ffc50 | |||
| c85079e9d0 | |||
| dec92322f1 | |||
| 72ea614d5e | |||
| 184ff6fb2d | |||
| 9830952461 | |||
| e9a2b0dcdb | |||
| 23d5c7180b | |||
| a661e77345 | |||
| 564b9a0c3e | |||
| 2ab6af1e48 | |||
| 22e9434a50 | |||
| 581d948c93 | |||
| 7721f47f59 | |||
| 49f295690a | |||
| 4b80a10969 | |||
| 6574dcc728 | |||
| 99bcfdcd0d | |||
| fcfe23d516 | |||
| e1b3ca4066 | |||
| 5a7eea53b1 | |||
| f9426a008e | |||
| 0bb7f4bd6a | |||
| da49a0ce40 | |||
| 80d67d49a0 | |||
| 6ca766d5ea | |||
| 5e3eb884ca | |||
| aef78b1ef1 | |||
| f1f5d8de7d | |||
| 535d9abce0 | |||
| 8679090bf3 | |||
| b12605274d | |||
| db1c6e659d | |||
| d72b18c47b | |||
| 81c2779731 | |||
| 163f5977a5 | |||
| 99ab1f0e81 | |||
| 02db3338fb | |||
| ca841c9248 | |||
| c78460289a | |||
| a16cbe7e5b | |||
| e986b024bc | |||
| bef9867b61 | |||
| d16e2b7992 | |||
| 20a00d517e | |||
| 9f247eb278 | |||
| b99bd08df9 | |||
| 72b5ede0da | |||
| 21998dcb9d | |||
| ba8c16acd7 | |||
| dd5e97bf14 | |||
| d90852336f | |||
| 849a4efda8 | |||
| 40ff1cb4c8 | |||
| 23c5289b7e | |||
| 7653107f0c | |||
| 2cb5bf146c | |||
| 4ebc3b5964 | |||
| 701ee719e6 | |||
| f99a5ff577 | |||
| 1a53838d97 | |||
| 2fc78a0fe2 | |||
| 60ea562560 | |||
| b0326d3078 | |||
| 752b91f118 | |||
| b0ae461139 | |||
| ee5905d237 | |||
| 5a8a050c46 | |||
| 7be8247b2f | |||
| 2881a645a5 | |||
| 98e86817bf | |||
| 3b92b9bb79 | |||
| 1b3545c82a | |||
| 2a5754600a | |||
| ff8b9d8375 | |||
| 1982fb51c9 | |||
| 0810e4a01c | |||
| 0f610b03d2 | |||
| 8feb285ca8 | |||
| c21431415b | |||
| f9d73761bb | |||
| 4c600311df | |||
| 827fd1da0e | |||
| 328cc89980 | |||
| cf6d26d25f | |||
| b67d2a265d | |||
| 8b23698852 | |||
| 6a467fc00e | |||
| fa2d36c5dc | |||
| a0cac54492 | |||
| 2059422955 | |||
| b35a2acfc8 | |||
| e77162f308 | |||
| 1c3b3b89be | |||
| 970ef0cec2 | |||
| 97ce2070d1 | |||
| b6e408aab8 | |||
| 6b3bf1b3ba | |||
| 5dd9c53176 | |||
| 5f82bdbf1b | |||
| 3109e7a4bb | |||
| 397d202f54 | |||
| 2597c235d9 | |||
| d222855cc8 | |||
| 308d02f72f | |||
| 35171c9222 | |||
| e9e74f1800 | |||
| 85d3b2d14b | |||
| 706b180a2c | |||
| beddbaf5c7 | |||
| a907301dcb | |||
| 1b1c2b1998 | |||
| e7865295dd | |||
| 6d8557608c | |||
| fd37be4dff | |||
| 92ffcb47e2 | |||
| c164d58a1a | |||
| 3459697cb4 | |||
| 31bb686fd5 | |||
| 5659a1e79e | |||
| b7549196da | |||
| a3ed49a5ed | |||
| e1ebc1e692 | |||
| d27684d280 | |||
| f9b3eff5ab | |||
| 34b479a1a4 | |||
| 6ee8ed02a9 | |||
| 73c0d57c94 | |||
| cbc15d733d | |||
| 61241140e8 | |||
| 250c483a6b | |||
| a394b564f4 | |||
| 2588368231 | |||
| d09cacebc7 | |||
| ddaab50b75 | |||
| e33ecf3665 | |||
| 26fdc7cc91 | |||
| 724f1772b7 | |||
| 2a29bb3ad9 | |||
| 3e7f870965 | |||
| 11f356e375 | |||
| 65cec7a2b9 | |||
| 4620ea6a44 | |||
| 3b702bd992 | |||
| bed9e118b6 | |||
| 8ba804e299 | |||
| 17b513eafb | |||
| ca6b23684e | |||
| 268cb0c6c5 | |||
| 5e8b52debf | |||
| 43f819e9e2 | |||
| 4533d6a7cd | |||
| 50134eb1ac | |||
| 4138fd3626 | |||
| b9ee6a9119 | |||
| d7a47264ef | |||
| 187bde37ca | |||
| 7edeb13be8 | |||
| e8d582600c | |||
| 7a446d53c0 | |||
| ba5b4ab166 | |||
| 985d08885e | |||
| 368756e4d5 | |||
| a1bc4dc2e4 | |||
| f9d61108ee | |||
| 3993969c41 | |||
| 9b9a4b6835 | |||
| 96bcde80af | |||
| bc790d6b87 | |||
| 2a4241323d | |||
| 0a3358f249 | |||
| 1573bf58c5 | |||
| 1c9607ec33 | |||
| e9126fdd9b | |||
| ab65914233 | |||
| 027b28ecb0 | |||
| 8870f907e8 | |||
| ca077342f3 | |||
| 454d453207 | |||
| 8378dd95fe | |||
| 7b63960db0 | |||
| 3e68a2c2bc | |||
| 4410c7cd94 | |||
| 93c7b092b3 | |||
| 624a6dd85c | |||
| 8f12dbf3b4 | |||
| 2ef71580ad | |||
| 4b244612c1 | |||
| b1a007dfb5 | |||
| e476f2375a | |||
| 0f04084f6c | |||
| 22226f3423 | |||
| 6e9cd25150 | |||
| bf3e3c60e5 | |||
| 988a406da8 | |||
| 0061054aaa | |||
| 56c26c5b55 | |||
| 8b998749f3 | |||
| b55399bd4b | |||
| 0d6c6c2a35 | |||
| 9475de28b3 | |||
| b6a41c85e1 | |||
| 457b5a011f | |||
| f73fd8ae95 | |||
| d5489a3e0d | |||
| 331730f8f5 | |||
| 60f513cbff | |||
| f84c67b98a | |||
| a1a278ee69 | |||
| 19241ed03d | |||
| 40577433aa | |||
| 1da0c1c890 | |||
| 4cfb7ddd42 | |||
| 5ae68b8c3b | |||
| 8fb59d391c | |||
| 2c81941567 | |||
| 7da72062b3 | |||
| 9a8cb48a53 | |||
| 8cb9f865f4 | |||
| dc843e8812 | |||
| 8d20259dfb | |||
| b753cf64d6 | |||
| 5b695d3deb | |||
| 286fc25aab | |||
| d378ce76e5 | |||
| fe7c91220f | |||
| 708d148d31 | |||
| 8b7ecc3f5c | |||
| ae610eca0d | |||
| 3a518b2a3c | |||
| f451e633cb | |||
| e1408a9f58 | |||
| 0c24c2df2e | |||
| a6aa9c652b | |||
| 521f839753 | |||
| 687b94374c | |||
| 6b32586e1f | |||
| ed00c13b15 | |||
| 378d6bb4ff | |||
| 662b4b94f4 | |||
| 19b73469dd | |||
| 165c041256 | |||
| 7e956f77f5 | |||
| 254de641f7 | |||
| 3ccb2e6e8d | |||
| 275b83cc52 | |||
| c420c78517 | |||
| 280c7bcf27 | |||
| 7b3cfab563 | |||
| ff5e1d337a | |||
| 853f47e4aa | |||
| 5b24ee8498 | |||
| a5cf424f08 | |||
| 6a2602f243 | |||
| 95b52b9f82 | |||
| 8723421bc3 | |||
| 67d9466e5a | |||
| 9928674b37 | |||
| b2cbff3bb6 | |||
| e48c22ffbd | |||
| 8f13a631e7 | |||
| 9b712613c5 | |||
| 9d95483de6 | |||
| cabc666505 | |||
| a3ea7c7c47 | |||
| 2032f51460 | |||
| 3d1fb9bc3a | |||
| 6ee92179d8 | |||
| 9404716322 | |||
| 2c8c3464b2 | |||
| dd8f248f7b | |||
| 9117bcaa41 | |||
| 76927a0301 | |||
| 145a2253e8 | |||
| c94496c9fe | |||
| 183b06bb9d | |||
| d9345b3874 | |||
| 5057329af7 | |||
| 259390868e | |||
| c9edbbe9b7 | |||
| 72ba4ea90a | |||
| cd135b16f6 | |||
| 821fb54934 | |||
| b8a8dc4562 | |||
| 1450eb5b65 | |||
| 665c3e9f33 | |||
| 80e1d6b6e8 | |||
| 8ee209585d | |||
| e1cafe7881 | |||
| cc164257a7 | |||
| 735ebd6c66 | |||
| f5486bde35 | |||
| 00f5f1722c | |||
| e025755a61 | |||
| 0f3685aca3 | |||
| 10b613c97d | |||
| 63db262f35 | |||
| f0de62906c | |||
| a9a6d7cbda | |||
| 1df1de2bb7 | |||
| 42eeab1cdb | |||
| 2c1d809e62 | |||
| f43ba0a51c | |||
| be33f1e6d4 | |||
| 7a95f3344c | |||
| 29a0e1f519 | |||
| 0ccb6dfc90 | |||
| 3e02023d9f | |||
| a4979fe851 | |||
| 9f2d3e0540 | |||
| a2802923e2 |
@@ -1,5 +1,6 @@
|
||||
.idea
|
||||
pkg
|
||||
vendor
|
||||
bin
|
||||
!bin/jasmine
|
||||
.idea/
|
||||
.svn/
|
||||
.DS_Store
|
||||
_site/
|
||||
.bundle/
|
||||
.pairs
|
||||
@@ -1,3 +1,3 @@
|
||||
[submodule "jasmine"]
|
||||
path = jasmine
|
||||
url = git://github.com/pivotal/jasmine.git
|
||||
[submodule "pages"]
|
||||
path = pages
|
||||
url = git@github.com:pivotal/jasmine.git
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
#jasmine-ruby is currently designed for use with bundler 0.8.0
|
||||
source :gemcutter
|
||||
|
||||
gem "jekyll", "0.6.2"
|
||||
gem "json_pure", "~>1.4.3"
|
||||
gem "ragaskar-jsdoc_helper"
|
||||
gem "rake", "0.8.7"
|
||||
gem "jeweler", "1.4.0"
|
||||
gem "gemcutter", "0.2.1"
|
||||
|
||||
gem "rspec", ">= 1.1.5", :only => :testing
|
||||
gem "rack", ">= 1.0.0", :only => :testing
|
||||
gem "thin", ">= 1.2.4", :only => :testing
|
||||
gem "selenium-rc", ">=2.1.0", :only => :testing
|
||||
gem "selenium-client", ">=1.2.17", :only => :testing
|
||||
|
||||
disable_system_gems
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2008 Pivotal Labs
|
||||
Copyright (c) 2008-2010 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -1,37 +1,28 @@
|
||||
jasmine-ruby
|
||||
============
|
||||
<a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a>
|
||||
=======
|
||||
**A JavaScript Testing Framework**
|
||||
|
||||
Jasmine Ruby dynamically serves HTML suites for [Jasmine](http://github.com/pivotal/jasmine)
|
||||
Want to use Jasmine in a project? Go HERE: [http://pivotal.github.com/jasmine/](http://pivotal.github.com/jasmine/)
|
||||
|
||||
To use:
|
||||
Want to contribute to Jasmine? Read on...
|
||||
|
||||
`(sudo) gem install jasmine`
|
||||
<i>(More developer docs to come...)</i>
|
||||
|
||||
Post-installation:
|
||||
## Support
|
||||
We now have a Google Group for support & discussion.
|
||||
|
||||
For Rails support, use
|
||||
* Discussion: [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js)
|
||||
* Group email: [jasmine-js@googlegroups.com](jasmine-js@googlegroups.com)
|
||||
* Current build status of Jasmine is visible at [ci.pivotallabs.com](http://ci.pivotallabs.com)
|
||||
* Pivotal Tracker project: [http://www.pivotaltracker.com/projects/10606](http://www.pivotaltracker.com/projects/10606)
|
||||
* Twitter: [@JasmineBDD](http://twitter.com/JasmineBDD)
|
||||
|
||||
`script/generate jasmine`
|
||||
## Maintainers
|
||||
* [Davis W. Frank](mailto:dwfrank@pivotallabs.com), Pivotal Labs
|
||||
* [Rajan Agaskar](mailto:rajan@pivotallabs.com), Pivotal Labs
|
||||
* [Christian Williams](mailto:xian@pivotallabs.com), Pivotal Labs
|
||||
|
||||
For other projects, use
|
||||
## Developers
|
||||
We welcome your contributions! Jasmine is currently maintained by Davis Frank ([infews](http://github.com/infews)), Rajan Agaskar ([ragaskar](http://github.com/ragaskar)), and Christian Williams ([Xian](http://github.com/Xian)). You can help us by removing all other recipients from your pull request.
|
||||
|
||||
`jasmine init`
|
||||
|
||||
After initializing a project, you may
|
||||
|
||||
`rake jasmine`
|
||||
|
||||
to set up a server. Opening localhost:8888 in a web browser will now run your jasmine specs.
|
||||
|
||||
You may also
|
||||
|
||||
`rake jasmine:ci`
|
||||
|
||||
which will run your Jasmine suites using selenium and rspec. This task is suitable for running in continuous integration environments.
|
||||
|
||||
Simple Configuration:
|
||||
|
||||
Customize `spec/javascripts/support/jasmine.yaml` to enumerate the source files, stylesheets, and spec files you would like the Jasmine runner to include.
|
||||
You may use dir glob strings.
|
||||
|
||||
It is also possible to add overrides into the `spec/javascripts/support/jasmine_config.rb` file directly if you require further customization.
|
||||
Copyright (c) 2008-2010 Pivotal Labs. This software is licensed under the MIT License.
|
||||
|
||||
@@ -1,66 +1,179 @@
|
||||
require "#{File.dirname(__FILE__)}/vendor/gems/environment"
|
||||
Bundler.require_env :rake
|
||||
def jasmine_sources
|
||||
sources = ["src/base.js", "src/util.js", "src/Env.js", "src/Reporter.js", "src/Block.js"]
|
||||
sources += Dir.glob('src/*.js').reject { |f| f == 'src/base.js' || sources.include?(f) }.sort
|
||||
sources
|
||||
end
|
||||
|
||||
$LOAD_PATH.unshift File.expand_path("#{File.dirname(__FILE__)}/lib")
|
||||
def jasmine_html_sources
|
||||
["src/html/TrivialReporter.js"]
|
||||
end
|
||||
|
||||
require 'spec'
|
||||
require 'spec/rake/spectask'
|
||||
def jasmine_version
|
||||
"#{version_hash['major']}.#{version_hash['minor']}.#{version_hash['build']}"
|
||||
end
|
||||
|
||||
desc "Run all examples"
|
||||
Spec::Rake::SpecTask.new('spec') do |t|
|
||||
t.spec_files = FileList['spec/**/*.rb']
|
||||
def version_hash
|
||||
require 'json'
|
||||
@version ||= JSON.parse(File.new("src/version.json").read);
|
||||
end
|
||||
|
||||
task :default => 'jasmine:dist'
|
||||
|
||||
def substitute_jasmine_version(filename)
|
||||
contents = File.read(filename)
|
||||
contents = contents.gsub(/##JASMINE_VERSION##/, (jasmine_version))
|
||||
contents = contents.gsub(/[^\n]*REMOVE_THIS_LINE_FROM_BUILD[^\n]*/, '')
|
||||
File.open(filename, 'w') { |f| f.write(contents) }
|
||||
end
|
||||
|
||||
namespace :jasmine do
|
||||
# require 'jasmine'
|
||||
require 'spec/jasmine_self_test_config'
|
||||
|
||||
# desc "Run continuous integration tests"
|
||||
# require "spec"
|
||||
# require 'spec/rake/spectask'
|
||||
# Spec::Rake::SpecTask.new(:ci) do |t|
|
||||
# t.spec_opts = ["--color", "--format", "specdoc"]
|
||||
# t.verbose = true
|
||||
# t.spec_files = [JasmineHelper.meta_spec_path]
|
||||
# end
|
||||
desc 'Prepares for distribution'
|
||||
task :dist => ['jasmine:build', 'jasmine:doc', 'jasmine:build_example_project', 'jasmine:fill_index_downloads']
|
||||
|
||||
task :server do
|
||||
puts "your tests are here:"
|
||||
puts " http://localhost:8888/run.html"
|
||||
desc 'Check jasmine sources for coding problems'
|
||||
task :lint do
|
||||
passed = true
|
||||
jasmine_sources.each do |src|
|
||||
lines = File.read(src).split(/\n/)
|
||||
lines.each_index do |i|
|
||||
line = lines[i]
|
||||
undefineds = line.scan(/.?undefined/)
|
||||
if undefineds.include?(" undefined") || undefineds.include?("\tundefined")
|
||||
puts "Dangerous undefined at #{src}:#{i}:\n > #{line}"
|
||||
passed = false
|
||||
end
|
||||
|
||||
JasmineSelfTestConfig.new.start_server
|
||||
end
|
||||
end
|
||||
|
||||
desc "Run specs via server"
|
||||
task :jasmine => ['jasmine:server']
|
||||
|
||||
|
||||
namespace :jeweler do
|
||||
|
||||
unless File.exists?('jasmine/lib')
|
||||
raise "Jasmine submodule isn't present. Run git submodule update --init"
|
||||
end
|
||||
|
||||
begin
|
||||
require 'jeweler'
|
||||
require 'rake'
|
||||
Jeweler::Tasks.new do |gemspec|
|
||||
gemspec.name = "jasmine"
|
||||
gemspec.summary = "Jasmine Ruby Runner"
|
||||
gemspec.description = "Javascript BDD test framework"
|
||||
gemspec.email = "ragaskar@gmail.com"
|
||||
gemspec.homepage = "http://github.com/pivotal/jasmine-ruby"
|
||||
gemspec.authors = ["Rajan Agaskar", "Christian Williams"]
|
||||
gemspec.executables = ["jasmine"]
|
||||
gemspec.files = FileList.new('generators/**/**', 'lib/**/**', 'jasmine/lib/**', 'jasmine/contrib/ruby/**', 'tasks/**', 'templates/**')
|
||||
gemspec.add_dependency('rspec', '>= 1.1.5')
|
||||
gemspec.add_dependency('json', '>= 1.1.9')
|
||||
gemspec.add_dependency('rack', '>= 1.0.0')
|
||||
gemspec.add_dependency('thin', '>= 1.2.4')
|
||||
gemspec.add_dependency('selenium-rc', '>=2.1.0')
|
||||
gemspec.add_dependency('selenium-client', '>=1.2.17')
|
||||
if line.scan(/window/).length > 0
|
||||
puts "Dangerous window at #{src}:#{i}:\n > #{line}"
|
||||
passed = false
|
||||
end
|
||||
end
|
||||
end
|
||||
Jeweler::GemcutterTasks.new
|
||||
|
||||
unless passed
|
||||
puts "Lint failed!"
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Builds lib/jasmine from source'
|
||||
task :build => :lint do
|
||||
puts 'Building Jasmine from source'
|
||||
|
||||
sources = jasmine_sources
|
||||
version = version_hash
|
||||
|
||||
old_jasmine_files = Dir.glob('lib/jasmine*.js')
|
||||
old_jasmine_files.each { |file| File.delete(file) }
|
||||
|
||||
File.open("lib/jasmine.js", 'w') do |jasmine|
|
||||
sources.each do |source_filename|
|
||||
jasmine.puts(File.read(source_filename))
|
||||
end
|
||||
|
||||
jasmine.puts %{
|
||||
jasmine.version_= {
|
||||
"major": #{version['major'].to_json},
|
||||
"minor": #{version['minor'].to_json},
|
||||
"build": #{version['build'].to_json},
|
||||
"revision": #{Time.now.to_i}
|
||||
};
|
||||
}
|
||||
end
|
||||
|
||||
File.open("lib/jasmine-html.js", 'w') do |jasmine_html|
|
||||
jasmine_html_sources.each do |source_filename|
|
||||
jasmine_html.puts(File.read(source_filename))
|
||||
end
|
||||
end
|
||||
|
||||
FileUtils.cp("src/html/jasmine.css", "lib/jasmine.css")
|
||||
end
|
||||
|
||||
task :need_pages_submodule do
|
||||
unless File.exists?('pages/index.html')
|
||||
raise "Jasmine pages submodule isn't present. Run git submodule update --init"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Build jasmine documentation"
|
||||
task :doc => :need_pages_submodule do
|
||||
puts 'Creating Jasmine Documentation'
|
||||
require 'rubygems'
|
||||
require 'jsdoc_helper'
|
||||
|
||||
FileUtils.rm_r "pages/jsdoc", :force => true
|
||||
|
||||
JsdocHelper::Rake::Task.new(:lambda_jsdoc) do |t|
|
||||
t[:files] = jasmine_sources << jasmine_html_sources
|
||||
t[:options] = "-a"
|
||||
t[:out] = "pages/jsdoc"
|
||||
end
|
||||
Rake::Task[:lambda_jsdoc].invoke
|
||||
end
|
||||
|
||||
desc "Build example project"
|
||||
task :build_example_project => :need_pages_submodule do
|
||||
require 'tmpdir'
|
||||
|
||||
temp_dir = File.join(Dir.tmpdir, 'jasmine-standalone-project')
|
||||
puts "Building Example Project in #{temp_dir}"
|
||||
FileUtils.rm_r temp_dir if File.exists?(temp_dir)
|
||||
Dir.mkdir(temp_dir)
|
||||
|
||||
root = File.expand_path(File.dirname(__FILE__))
|
||||
FileUtils.cp_r File.join(root, 'example/.'), File.join(temp_dir)
|
||||
substitute_jasmine_version(File.join(temp_dir, "SpecRunner.html"))
|
||||
|
||||
lib_dir = File.join(temp_dir, "lib/jasmine-#{jasmine_version}")
|
||||
FileUtils.mkdir_p(lib_dir)
|
||||
{
|
||||
"lib/jasmine.js" => "jasmine.js",
|
||||
"lib/jasmine-html.js" => "jasmine-html.js",
|
||||
"src/html/jasmine.css" => "jasmine.css",
|
||||
"MIT.LICENSE" => "MIT.LICENSE"
|
||||
}.each_pair do |src, dest|
|
||||
FileUtils.cp(File.join(root, src), File.join(lib_dir, dest))
|
||||
end
|
||||
|
||||
dist_dir = File.join(root, 'pages/downloads')
|
||||
zip_file_name = File.join(dist_dir, "jasmine-standalone-#{jasmine_version}.zip")
|
||||
puts "Zipping Example Project and moving to #{zip_file_name}"
|
||||
FileUtils.mkdir(dist_dir) unless File.exist?(dist_dir)
|
||||
if File.exist?(zip_file_name)
|
||||
puts "WARNING!!! #{zip_file_name} already exists!"
|
||||
FileUtils.rm(zip_file_name)
|
||||
end
|
||||
exec "cd #{temp_dir} && zip -r #{zip_file_name} . -x .[a-zA-Z0-9]*"
|
||||
end
|
||||
|
||||
task :fill_index_downloads do
|
||||
require 'digest/sha1'
|
||||
|
||||
download_html = "<!-- START_DOWNLOADS -->\n"
|
||||
download_html += "<table>\n<tr><th></th><th>Version</th><th>Size</th><th>Date</th><th>SHA1</th></tr>\n"
|
||||
Dir.glob('pages/downloads/*.zip').sort.reverse.each do |f|
|
||||
sha1 = Digest::SHA1.hexdigest File.read(f)
|
||||
|
||||
fn = f.sub(/^pages\//, '')
|
||||
version = /jasmine-standalone-(.*).zip/.match(f)[1]
|
||||
download_html += "<tr>\n"
|
||||
download_html += "<td class=\"link\"><a href='#{fn}'>#{fn.sub(/downloads\//, '')}</a></td>\n"
|
||||
download_html += "<td class=\"version\">#{version}</td>\n"
|
||||
download_html += "<td class=\"size\">#{File.size(f) / 1024}k</td>\n"
|
||||
download_html += "<td class=\"date\">#{File.mtime(f).strftime("%Y/%m/%d %H:%M:%S %Z")}</td>\n"
|
||||
download_html += "<td class=\"sha\">#{sha1}</td>\n"
|
||||
download_html += "</tr>\n"
|
||||
end
|
||||
download_html += "</table>\n<!-- END_DOWNLOADS -->"
|
||||
|
||||
index_page = File.read('pages/index.html')
|
||||
matcher = /<!-- START_DOWNLOADS -->.*<!-- END_DOWNLOADS -->/m
|
||||
index_page = index_page.sub(matcher, download_html)
|
||||
File.open('pages/index.html', 'w') {|f| f.write(index_page)}
|
||||
puts "rewrote that file"
|
||||
end
|
||||
end
|
||||
|
||||
task :jasmine => ['jasmine:dist']
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
:patch: 5
|
||||
:major: 0
|
||||
:build:
|
||||
:minor: 4
|
||||
@@ -1,58 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
require 'rubygems'
|
||||
require 'rake'
|
||||
|
||||
def cwd
|
||||
File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
||||
end
|
||||
|
||||
def expand(*paths)
|
||||
File.expand_path(File.join(*paths))
|
||||
end
|
||||
|
||||
def template_path(filepath)
|
||||
expand(cwd, File.join("generators/jasmine/templates", filepath))
|
||||
end
|
||||
|
||||
def dest_path(filepath)
|
||||
expand(Dir.pwd, filepath)
|
||||
end
|
||||
|
||||
def copy_unless_exists(relative_path, dest_path = nil)
|
||||
unless File.exist?(dest_path(relative_path))
|
||||
File.copy(template_path(relative_path), dest_path(dest_path || relative_path))
|
||||
end
|
||||
end
|
||||
|
||||
if ARGV[0] == 'init'
|
||||
require 'ftools'
|
||||
File.makedirs('spec/javascripts')
|
||||
File.makedirs('spec/javascripts/support')
|
||||
|
||||
copy_unless_exists('spec/javascripts/SpecHelper.js')
|
||||
copy_unless_exists('spec/javascripts/ExampleSpec.js')
|
||||
copy_unless_exists('spec/javascripts/support/jasmine_config.rb')
|
||||
copy_unless_exists('spec/javascripts/support/jasmine_runner.rb')
|
||||
|
||||
rails_tasks_dir = dest_path('lib/tasks')
|
||||
if File.exist?(rails_tasks_dir)
|
||||
copy_unless_exists('lib/tasks/jasmine.rake')
|
||||
copy_unless_exists('spec/javascripts/support/jasmine-rails.yml', 'spec/javascripts/support/jasmine.yml')
|
||||
else
|
||||
copy_unless_exists('spec/javascripts/support/jasmine.yml')
|
||||
write_mode = 'w'
|
||||
if File.exist?(dest_path('Rakefile'))
|
||||
load dest_path('Rakefile')
|
||||
write_mode = 'a'
|
||||
end
|
||||
unless Rake::Task.task_defined?('jasmine')
|
||||
File.open(dest_path('Rakefile'), write_mode) do |f|
|
||||
f.write(File.read(template_path('lib/tasks/jasmine.rake')))
|
||||
end
|
||||
end
|
||||
end
|
||||
File.open(template_path('INSTALL'), 'r').each_line do |line|
|
||||
puts line
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Project-specific configuration for CruiseControl.rb
|
||||
Project.configure do |project|
|
||||
|
||||
# Send email notifications about broken and fixed builds to email1@your.site, email2@your.site (default: send to nobody)
|
||||
# project.email_notifier.emails = ['email1@your.site', 'email2@your.site']
|
||||
|
||||
# Set email 'from' field to john@doe.com:
|
||||
# project.email_notifier.from = 'john@doe.com'
|
||||
|
||||
# Build the project by invoking rake task 'custom'
|
||||
project.rake_task = 'jasmine:test:ci:saucelabs'
|
||||
|
||||
# Build the project by invoking shell script "build_my_app.sh". Keep in mind that when the script is invoked,
|
||||
# current working directory is <em>[cruise data]</em>/projects/your_project/work, so if you do not keep build_my_app.sh
|
||||
# in version control, it should be '../build_my_app.sh' instead
|
||||
#project.build_command = 'cp ../saucelabs.yml .'
|
||||
|
||||
# Ping Subversion for new revisions every 5 minutes (default: 30 seconds)
|
||||
# project.scheduler.polling_interval = 5.minutes
|
||||
|
||||
end
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Jasmine Test Runner</title>
|
||||
<link rel="stylesheet" type="text/css" href="lib/jasmine-##JASMINE_VERSION##/jasmine.css">
|
||||
<script type="text/javascript" src="lib/jasmine-##JASMINE_VERSION##/jasmine.js"></script>
|
||||
<script type="text/javascript" src="lib/jasmine-##JASMINE_VERSION##/jasmine-html.js"></script>
|
||||
|
||||
<!-- include source files here... -->
|
||||
<script type="text/javascript" src="src/Player.js"></script>
|
||||
<script type="text/javascript" src="src/Song.js"></script>
|
||||
|
||||
<!-- include spec files here... -->
|
||||
<script type="text/javascript" src="spec/SpecHelper.js"></script>
|
||||
<script type="text/javascript" src="spec/PlayerSpec.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="REMOVE_THIS_LINE_FROM_BUILD"><p>You must be trying to look at examples in the Jasmine source tree.</p><p>Please download a distribution version of Jasmine at <a href="http://pivotal.github.com/jasmine/">http://pivotal.github.com/jasmine/</a>.</p></div>
|
||||
<script type="text/javascript">
|
||||
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
|
||||
jasmine.getEnv().execute();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,58 @@
|
||||
describe("Player", function() {
|
||||
var player;
|
||||
var song;
|
||||
|
||||
beforeEach(function() {
|
||||
player = new Player();
|
||||
song = new Song();
|
||||
});
|
||||
|
||||
it("should be able to play a Song", function() {
|
||||
player.play(song);
|
||||
expect(player.currentlyPlayingSong).toEqual(song);
|
||||
|
||||
//demonstrates use of custom matcher
|
||||
expect(player).toBePlaying(song);
|
||||
});
|
||||
|
||||
describe("when song has been paused", function() {
|
||||
beforeEach(function() {
|
||||
player.play(song);
|
||||
player.pause();
|
||||
});
|
||||
|
||||
it("should indicate that the song is currently paused", function() {
|
||||
expect(player.isPlaying).toBeFalsy();
|
||||
|
||||
// demonstrates use of 'not' with a custom matcher
|
||||
expect(player).not.toBePlaying(song);
|
||||
});
|
||||
|
||||
it("should be possible to resume", function() {
|
||||
player.resume();
|
||||
expect(player.isPlaying).toBeTruthy();
|
||||
expect(player.currentlyPlayingSong).toEqual(song);
|
||||
});
|
||||
});
|
||||
|
||||
// demonstrates use of spies to intercept and test method calls
|
||||
it("tells the current song if the user has made it a favorite", function() {
|
||||
spyOn(song, 'persistFavoriteStatus');
|
||||
|
||||
player.play(song);
|
||||
player.makeFavorite();
|
||||
|
||||
expect(song.persistFavoriteStatus).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
//demonstrates use of expected exceptions
|
||||
describe("#resume", function() {
|
||||
it("should throw an exception if song is already playing", function() {
|
||||
player.play(song);
|
||||
|
||||
expect(function() {
|
||||
player.resume();
|
||||
}).toThrow("song is already playing");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
beforeEach(function() {
|
||||
this.addMatchers({
|
||||
toBePlaying: function(expectedSong) {
|
||||
var player = this.actual;
|
||||
return player.currentlyPlayingSong === expectedSong
|
||||
&& player.isPlaying;
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
function Player() {
|
||||
}
|
||||
Player.prototype.play = function(song) {
|
||||
this.currentlyPlayingSong = song;
|
||||
this.isPlaying = true;
|
||||
};
|
||||
|
||||
Player.prototype.pause = function() {
|
||||
this.isPlaying = false;
|
||||
};
|
||||
|
||||
Player.prototype.resume = function() {
|
||||
if (this.isPlaying) {
|
||||
throw new Error("song is already playing");
|
||||
}
|
||||
|
||||
this.isPlaying = true;
|
||||
};
|
||||
|
||||
Player.prototype.makeFavorite = function() {
|
||||
this.currentlyPlayingSong.persistFavoriteStatus(true);
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
function Song() {
|
||||
}
|
||||
|
||||
Song.prototype.persistFavoriteStatus = function(value) {
|
||||
// something complicated
|
||||
throw new Error("not yet implemented");
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
class JasmineGenerator < Rails::Generator::Base
|
||||
def manifest
|
||||
record do |m|
|
||||
|
||||
m.directory "spec/javascripts"
|
||||
m.file "spec/javascripts/SpecHelper.js", "spec/javascripts/SpecHelper.js"
|
||||
m.file "spec/javascripts/ExampleSpec.js", "spec/javascripts/ExampleSpec.js"
|
||||
|
||||
m.directory "spec/javascripts/support"
|
||||
m.file "spec/javascripts/support/jasmine_config.rb", "spec/javascripts/support/jasmine_config.rb"
|
||||
m.file "spec/javascripts/support/jasmine_runner.rb", "spec/javascripts/support/jasmine_runner.rb"
|
||||
m.file "spec/javascripts/support/jasmine-rails.yml", "spec/javascripts/support/jasmine.yml"
|
||||
|
||||
m.directory "lib/tasks"
|
||||
m.file "lib/tasks/jasmine.rake", "lib/tasks/jasmine.rake"
|
||||
|
||||
m.readme "INSTALL"
|
||||
end
|
||||
end
|
||||
|
||||
def file_name
|
||||
"create_blog"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,9 +0,0 @@
|
||||
Jasmine has been installed with example specs.
|
||||
|
||||
To run the server:
|
||||
|
||||
rake jasmine
|
||||
|
||||
To run the automated CI task with Selenium:
|
||||
|
||||
rake jasmine:ci
|
||||
@@ -1,23 +0,0 @@
|
||||
namespace :jasmine do
|
||||
require 'jasmine'
|
||||
|
||||
desc "Run continuous integration tests"
|
||||
require "spec"
|
||||
require 'spec/rake/spectask'
|
||||
Spec::Rake::SpecTask.new(:ci) do |t|
|
||||
t.spec_opts = ["--color", "--format", "specdoc"]
|
||||
t.verbose = true
|
||||
t.spec_files = ['spec/javascripts/support/jasmine_runner.rb']
|
||||
end
|
||||
task :server do
|
||||
require 'spec/javascripts/support/jasmine_config'
|
||||
|
||||
puts "your tests are here:"
|
||||
puts " http://localhost:8888/run.html"
|
||||
|
||||
Jasmine::Config.new.start_server
|
||||
end
|
||||
end
|
||||
|
||||
desc "Run specs via server"
|
||||
task :jasmine => ['jasmine:server']
|
||||
@@ -1,11 +0,0 @@
|
||||
describe('Example', 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 +0,0 @@
|
||||
//You may load required files here, or create test-runner-wide environment settings.
|
||||
@@ -1,20 +0,0 @@
|
||||
# Return an array of filepaths relative to src_dir to include before jasmine specs.
|
||||
src_files:
|
||||
- javascripts/prototype.js
|
||||
- javascripts/effects.js
|
||||
- javascripts/controls.js
|
||||
- javascripts/dragdrop.js
|
||||
- javascripts/application.js
|
||||
|
||||
# Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
|
||||
stylesheets:
|
||||
- stylesheets/**/*.css
|
||||
# Return an array of filepaths relative to spec_dir to include before jasmine specs.
|
||||
spec_files:
|
||||
- **/*.js
|
||||
|
||||
# Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
|
||||
src_dir: public
|
||||
|
||||
# Spec directory path. Your spec_files must be returned relative to this path.
|
||||
spec_dir: spec/javascripts
|
||||
@@ -1,20 +0,0 @@
|
||||
# Return an array of filepaths relative to src_dir to include before jasmine specs.
|
||||
#src_files:
|
||||
# - lib/source1.js
|
||||
# - lib/source2.js
|
||||
# - dist/**/*.js
|
||||
|
||||
# Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
|
||||
#stylesheets:
|
||||
# - css/style.css
|
||||
# - stylesheets/*.css
|
||||
|
||||
# Return an array of filepaths relative to spec_dir to include before jasmine specs.
|
||||
#spec_files:
|
||||
# - **/*.js
|
||||
|
||||
# Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
|
||||
#src_dir:
|
||||
|
||||
# Spec directory path. Your spec_files must be returned relative to this path.
|
||||
#spec_dir: spec/javascripts
|
||||
@@ -1,61 +0,0 @@
|
||||
require 'jasmine'
|
||||
|
||||
class Jasmine::Config
|
||||
|
||||
# Override these methods if necessary
|
||||
|
||||
# def project_root
|
||||
# Dir.pwd
|
||||
# end
|
||||
|
||||
# Path to your jasmine.yml
|
||||
# def simple_config_file
|
||||
# File.join(project_root, 'spec/javascripts/support/jasmine.yml')
|
||||
# end
|
||||
|
||||
# Source directory path. Your src_files must be returned relative to this path.
|
||||
# def src_dir
|
||||
# if simple_config['src_dir']
|
||||
# File.join(project_root, simple_config['src_dir'])
|
||||
# else
|
||||
# project_root
|
||||
# end
|
||||
# end
|
||||
|
||||
# Spec directory path. Your spec_files must be returned relative to this path.
|
||||
# def spec_dir
|
||||
# if simple_config['spec_dir']
|
||||
# File.join(project_root, simple_config['spec_dir'])
|
||||
# else
|
||||
# File.join(project_root, 'spec/javascripts')
|
||||
# end
|
||||
# end
|
||||
|
||||
# Return an array of filepaths relative to src_dir to include before jasmine specs.
|
||||
# def src_files
|
||||
# files = []
|
||||
# if simple_config['src_files']
|
||||
# files = simple_config['src_files'].collect {|filepath| Dir.glob(filepath)}
|
||||
# end
|
||||
# files
|
||||
# end
|
||||
|
||||
# Return an array of filepaths relative to spec_dir to include before jasmine specs.
|
||||
# def spec_files
|
||||
# files = match_files(spec_dir, "**/*.js")
|
||||
# if simple_config['spec_files']
|
||||
# files = simple_config['spec_files'].collect {|filepath| Dir.glob(filepath)}
|
||||
# end
|
||||
# files
|
||||
# end
|
||||
|
||||
# Return an array of filepaths relative to src_dir to include before jasmine specs.
|
||||
# def stylesheets
|
||||
# files = []
|
||||
# if simple_config['stylesheets']
|
||||
# files = simple_config['stylesheets'].collect {|filepath| Dir.glob(filepath)}
|
||||
# end
|
||||
# files
|
||||
# end
|
||||
|
||||
end
|
||||
@@ -1,17 +0,0 @@
|
||||
require 'rubygems'
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), 'jasmine_config'))
|
||||
|
||||
jasmine_config = Jasmine::Config.new
|
||||
spec_builder = Jasmine::SpecBuilder.new(jasmine_config)
|
||||
|
||||
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
|
||||
|
After Width: | Height: | Size: 722 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 759 B |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 802 B |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 768 B |
|
After Width: | Height: | Size: 1.7 KiB |
@@ -1,2 +0,0 @@
|
||||
jasmine_bin = File.expand_path(File.join(File.dirname(__FILE__), 'bin', 'jasmine'))
|
||||
`#{jasmine_bin} init`
|
||||
@@ -1,87 +0,0 @@
|
||||
# Generated by jeweler
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = %q{jasmine}
|
||||
s.version = "0.4.5"
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = ["Rajan Agaskar", "Christian Williams"]
|
||||
s.date = %q{2010-02-24}
|
||||
s.default_executable = %q{jasmine}
|
||||
s.description = %q{Javascript BDD test framework}
|
||||
s.email = %q{ragaskar@gmail.com}
|
||||
s.executables = ["jasmine"]
|
||||
s.extra_rdoc_files = [
|
||||
"README.markdown"
|
||||
]
|
||||
s.files = [
|
||||
"generators/jasmine/jasmine_generator.rb",
|
||||
"generators/jasmine/templates/INSTALL",
|
||||
"generators/jasmine/templates/lib/tasks/jasmine.rake",
|
||||
"generators/jasmine/templates/spec/javascripts/ExampleSpec.js",
|
||||
"generators/jasmine/templates/spec/javascripts/SpecHelper.js",
|
||||
"generators/jasmine/templates/spec/javascripts/support/jasmine-rails.yml",
|
||||
"generators/jasmine/templates/spec/javascripts/support/jasmine.yml",
|
||||
"generators/jasmine/templates/spec/javascripts/support/jasmine_config.rb",
|
||||
"generators/jasmine/templates/spec/javascripts/support/jasmine_runner.rb",
|
||||
"jasmine/contrib/ruby/jasmine_runner.rb",
|
||||
"jasmine/contrib/ruby/jasmine_spec_builder.rb",
|
||||
"jasmine/contrib/ruby/run.html",
|
||||
"jasmine/lib/TrivialReporter.js",
|
||||
"jasmine/lib/consolex.js",
|
||||
"jasmine/lib/jasmine-0.10.1.js",
|
||||
"jasmine/lib/jasmine.css",
|
||||
"jasmine/lib/json2.js",
|
||||
"lib/jasmine.rb",
|
||||
"lib/jasmine/base.rb",
|
||||
"lib/jasmine/config.rb",
|
||||
"lib/jasmine/run.html.erb",
|
||||
"lib/jasmine/selenium_driver.rb",
|
||||
"lib/jasmine/server.rb",
|
||||
"lib/jasmine/spec_builder.rb"
|
||||
]
|
||||
s.homepage = %q{http://github.com/pivotal/jasmine-ruby}
|
||||
s.rdoc_options = ["--charset=UTF-8"]
|
||||
s.require_paths = ["lib"]
|
||||
s.rubygems_version = %q{1.3.5}
|
||||
s.summary = %q{Jasmine Ruby Runner}
|
||||
s.test_files = [
|
||||
"spec/config_spec.rb",
|
||||
"spec/jasmine_self_test_config.rb",
|
||||
"spec/jasmine_self_test_spec.rb",
|
||||
"spec/server_spec.rb",
|
||||
"spec/spec_helper.rb"
|
||||
]
|
||||
|
||||
if s.respond_to? :specification_version then
|
||||
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||
s.specification_version = 3
|
||||
|
||||
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
||||
s.add_runtime_dependency(%q<rspec>, [">= 1.1.5"])
|
||||
s.add_runtime_dependency(%q<json>, [">= 1.1.9"])
|
||||
s.add_runtime_dependency(%q<rack>, [">= 1.0.0"])
|
||||
s.add_runtime_dependency(%q<thin>, [">= 1.2.4"])
|
||||
s.add_runtime_dependency(%q<selenium-rc>, [">= 2.1.0"])
|
||||
s.add_runtime_dependency(%q<selenium-client>, [">= 1.2.17"])
|
||||
else
|
||||
s.add_dependency(%q<rspec>, [">= 1.1.5"])
|
||||
s.add_dependency(%q<json>, [">= 1.1.9"])
|
||||
s.add_dependency(%q<rack>, [">= 1.0.0"])
|
||||
s.add_dependency(%q<thin>, [">= 1.2.4"])
|
||||
s.add_dependency(%q<selenium-rc>, [">= 2.1.0"])
|
||||
s.add_dependency(%q<selenium-client>, [">= 1.2.17"])
|
||||
end
|
||||
else
|
||||
s.add_dependency(%q<rspec>, [">= 1.1.5"])
|
||||
s.add_dependency(%q<json>, [">= 1.1.9"])
|
||||
s.add_dependency(%q<rack>, [">= 1.0.0"])
|
||||
s.add_dependency(%q<thin>, [">= 1.2.4"])
|
||||
s.add_dependency(%q<selenium-rc>, [">= 2.1.0"])
|
||||
s.add_dependency(%q<selenium-client>, [">= 1.2.17"])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
jasmine.TrivialReporter = function(doc) {
|
||||
this.document = doc || document;
|
||||
this.suiteDivs = {};
|
||||
this.logRunningSpecs = false;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
|
||||
var el = document.createElement(type);
|
||||
|
||||
for (var i = 2; i < arguments.length; i++) {
|
||||
var child = arguments[i];
|
||||
|
||||
if (typeof child === 'string') {
|
||||
el.appendChild(document.createTextNode(child));
|
||||
} else {
|
||||
if (child) { el.appendChild(child); }
|
||||
}
|
||||
}
|
||||
|
||||
for (var attr in attrs) {
|
||||
if (attr == "className") {
|
||||
el[attr] = attrs[attr];
|
||||
} else {
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
||||
var showPassed, showSkipped;
|
||||
|
||||
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
|
||||
this.createDom('div', { className: 'banner' },
|
||||
this.createDom('div', { className: 'logo' },
|
||||
this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "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);
|
||||
|
||||
var suites = runner.suites();
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
var suite = suites[i];
|
||||
var suiteDiv = this.createDom('div', { className: 'suite' },
|
||||
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.id] = suiteDiv;
|
||||
var parentDiv = this.outerDiv;
|
||||
if (suite.parentSuite) {
|
||||
parentDiv = this.suiteDivs[suite.parentSuite.id];
|
||||
}
|
||||
parentDiv.appendChild(suiteDiv);
|
||||
}
|
||||
|
||||
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) {
|
||||
var results = runner.results();
|
||||
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
|
||||
this.runnerDiv.setAttribute("class", className);
|
||||
//do it twice for IE
|
||||
this.runnerDiv.setAttribute("className", className);
|
||||
var specs = runner.specs();
|
||||
var specCount = 0;
|
||||
for (var i = 0; i < specs.length; i++) {
|
||||
if (this.specFilter(specs[i])) {
|
||||
specCount++;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
var results = suite.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.totalCount == 0) { // todo: change this to check results.skipped
|
||||
status = 'skipped';
|
||||
}
|
||||
this.suiteDivs[suite.id].className += " " + status;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
|
||||
if (this.logRunningSpecs) {
|
||||
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
|
||||
var results = spec.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.skipped) {
|
||||
status = 'skipped';
|
||||
}
|
||||
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()),
|
||||
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.type == 'log') {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||
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.id].appendChild(specDiv);
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.log = function() {
|
||||
var console = jasmine.getGlobal().console;
|
||||
if (console && console.log) console.log.apply(console, arguments);
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.getLocation = function() {
|
||||
return this.document.location;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
|
||||
var paramMap = {};
|
||||
var params = this.getLocation().search.substring(1).split('&');
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var p = params[i].split('=');
|
||||
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
||||
}
|
||||
|
||||
if (!paramMap["spec"]) return true;
|
||||
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
|
||||
};
|
||||
@@ -0,0 +1,166 @@
|
||||
body {
|
||||
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
|
||||
}
|
||||
|
||||
|
||||
.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 {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
|
||||
.options {
|
||||
text-align: right;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.suite {
|
||||
border: 1px outset gray;
|
||||
margin: 5px 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.suite .suite {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.suite.passed {
|
||||
background-color: #dfd;
|
||||
}
|
||||
|
||||
.suite.failed {
|
||||
background-color: #fdd;
|
||||
}
|
||||
|
||||
.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: #fbb;
|
||||
}
|
||||
|
||||
.skipped {
|
||||
color: #777;
|
||||
background-color: #eee;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*.resultMessage {*/
|
||||
/*white-space: pre;*/
|
||||
/*}*/
|
||||
|
||||
.resultMessage span.result {
|
||||
display: block;
|
||||
line-height: 2em;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.resultMessage .mismatch {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.stackTrace {
|
||||
white-space: pre;
|
||||
font-size: .8em;
|
||||
margin-left: 10px;
|
||||
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;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
require 'jasmine/base'
|
||||
require 'jasmine/config'
|
||||
require 'jasmine/server'
|
||||
require 'jasmine/selenium_driver'
|
||||
|
||||
require 'jasmine/spec_builder'
|
||||
@@ -1,63 +0,0 @@
|
||||
require 'socket'
|
||||
require 'erb'
|
||||
require 'json'
|
||||
|
||||
module Jasmine
|
||||
def self.root
|
||||
File.expand_path(File.join(File.dirname(__FILE__), '../../jasmine'))
|
||||
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
|
||||
end
|
||||
@@ -1,163 +0,0 @@
|
||||
module Jasmine
|
||||
class Config
|
||||
require 'yaml'
|
||||
|
||||
def initialize(options = {})
|
||||
require 'selenium_rc'
|
||||
@selenium_jar_path = SeleniumRC::Server.allocate.jar_path
|
||||
@options = options
|
||||
|
||||
@browser = options[:browser] ? options.delete(:browser) : 'firefox'
|
||||
@selenium_pid = nil
|
||||
@jasmine_server_pid = nil
|
||||
end
|
||||
|
||||
def start_server(port = 8888)
|
||||
Jasmine::Server.new(port, self).start
|
||||
end
|
||||
|
||||
def start
|
||||
start_servers
|
||||
@client = Jasmine::SeleniumDriver.new("localhost", @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/")
|
||||
@client.connect
|
||||
end
|
||||
|
||||
def stop
|
||||
@client.disconnect
|
||||
stop_servers
|
||||
end
|
||||
|
||||
def start_servers
|
||||
@jasmine_server_port = Jasmine::find_unused_port
|
||||
@selenium_server_port = Jasmine::find_unused_port
|
||||
|
||||
server = Jasmine::Server.new(@jasmine_server_port, self)
|
||||
|
||||
@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_server_pid = fork do
|
||||
Process.setpgrp
|
||||
server.start
|
||||
exit! 0
|
||||
end
|
||||
puts "jasmine server started. pid is #{@jasmine_server_pid}"
|
||||
|
||||
Jasmine::wait_for_listener(@selenium_server_port, "selenium server")
|
||||
Jasmine::wait_for_listener(@jasmine_server_port, "jasmine server")
|
||||
end
|
||||
|
||||
def stop_servers
|
||||
puts "shutting down the servers..."
|
||||
Jasmine::kill_process_group(@selenium_pid) if @selenium_pid
|
||||
Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_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
|
||||
|
||||
def match_files(dir, patterns)
|
||||
dir = File.expand_path(dir)
|
||||
patterns.collect do |pattern|
|
||||
Dir.glob(File.join(dir, pattern)).collect {|f| f.sub("#{dir}/", "")}.sort
|
||||
end.flatten
|
||||
end
|
||||
|
||||
def simple_config
|
||||
config = File.exist?(simple_config_file) ? File.open(simple_config_file) { |yf| YAML::load( yf ) } : false
|
||||
config || {}
|
||||
end
|
||||
|
||||
|
||||
def spec_path
|
||||
"/__spec__"
|
||||
end
|
||||
|
||||
def root_path
|
||||
"/__root__"
|
||||
end
|
||||
|
||||
def mappings
|
||||
{
|
||||
spec_path => spec_dir,
|
||||
root_path => project_root
|
||||
}
|
||||
end
|
||||
|
||||
def js_files
|
||||
src_files.collect {|f| "/" + f } + spec_files.collect {|f| File.join(spec_path, f) }
|
||||
end
|
||||
|
||||
def css_files
|
||||
stylesheets.collect {|f| "/" + f }
|
||||
end
|
||||
|
||||
def spec_files_full_paths
|
||||
spec_files.collect {|spec_file| File.join(spec_dir, spec_file) }
|
||||
end
|
||||
|
||||
def project_root
|
||||
Dir.pwd
|
||||
end
|
||||
|
||||
def simple_config_file
|
||||
File.join(project_root, 'spec/javascripts/support/jasmine.yml')
|
||||
end
|
||||
|
||||
def src_dir
|
||||
if simple_config['src_dir']
|
||||
File.join(project_root, simple_config['src_dir'])
|
||||
else
|
||||
project_root
|
||||
end
|
||||
end
|
||||
|
||||
def spec_dir
|
||||
if simple_config['spec_dir']
|
||||
File.join(project_root, simple_config['spec_dir'])
|
||||
else
|
||||
File.join(project_root, 'spec/javascripts')
|
||||
end
|
||||
end
|
||||
|
||||
def src_files
|
||||
files = []
|
||||
if simple_config['src_files']
|
||||
files = match_files(src_dir, simple_config['src_files'])
|
||||
end
|
||||
files
|
||||
end
|
||||
|
||||
def spec_files
|
||||
files = match_files(spec_dir, "**/*.js")
|
||||
if simple_config['spec_files']
|
||||
files = match_files(spec_dir, simple_config['spec_files'])
|
||||
end
|
||||
files
|
||||
end
|
||||
|
||||
def stylesheets
|
||||
files = []
|
||||
if simple_config['stylesheets']
|
||||
files = match_files(src_dir, simple_config['stylesheets'])
|
||||
end
|
||||
files
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -1,43 +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 %>
|
||||
|
||||
<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>
|
||||
|
||||
<% js_files.each do |js_file| %>
|
||||
<script src="<%= js_file %>" type="text/javascript"></script>
|
||||
<% end %>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="jasmine_content"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,44 +0,0 @@
|
||||
module Jasmine
|
||||
class SeleniumDriver
|
||||
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\":#{result}}")["result"]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,133 +0,0 @@
|
||||
module Jasmine
|
||||
class RunAdapter
|
||||
def initialize(config)
|
||||
@config = config
|
||||
@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",
|
||||
]
|
||||
@jasmine_stylesheets = ["/__JASMINE_ROOT__/lib/jasmine.css"]
|
||||
end
|
||||
|
||||
def call(env)
|
||||
return not_found if env["PATH_INFO"] != "/"
|
||||
return [200,{ 'Content-Type' => 'text/html' }, ''] if (env['REQUEST_METHOD'] == 'HEAD')
|
||||
run if env['REQUEST_METHOD'] == 'GET'
|
||||
end
|
||||
|
||||
def not_found
|
||||
body = "File not found: #{@path_info}\n"
|
||||
[404, {"Content-Type" => "text/plain",
|
||||
"Content-Length" => body.size.to_s,
|
||||
"X-Cascade" => "pass"},
|
||||
[body]]
|
||||
end
|
||||
|
||||
#noinspection RubyUnusedLocalVariable
|
||||
def run
|
||||
jasmine_files = @jasmine_files
|
||||
css_files = @jasmine_stylesheets + (@config.css_files || [])
|
||||
js_files = @config.js_files
|
||||
|
||||
body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html.erb"))).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(config)
|
||||
@config = config
|
||||
end
|
||||
|
||||
def call(env)
|
||||
spec_files = @config.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 Server
|
||||
attr_reader :thin
|
||||
|
||||
def initialize(port, config)
|
||||
@port = port
|
||||
@config = config
|
||||
|
||||
require 'thin'
|
||||
thin_config = {
|
||||
'/__suite__' => Jasmine::FocusedSuite.new(@config),
|
||||
'/run.html' => Jasmine::Redirect.new('/'),
|
||||
'/' => Jasmine::RunAdapter.new(@config)
|
||||
}
|
||||
|
||||
@config.mappings.each do |from, to|
|
||||
thin_config[from] = Rack::File.new(to)
|
||||
end
|
||||
|
||||
thin_config["/__JASMINE_ROOT__"] = Rack::File.new(Jasmine.root)
|
||||
|
||||
app = Rack::Cascade.new([
|
||||
Rack::URLMap.new({'/' => Rack::File.new(@config.src_dir)}),
|
||||
Rack::URLMap.new(thin_config)
|
||||
# JsAlert.new
|
||||
])
|
||||
# Thin::Logging.trace = true
|
||||
@thin = Thin::Server.new('0.0.0.0', @port, app)
|
||||
end
|
||||
|
||||
def start
|
||||
begin
|
||||
thin.start
|
||||
rescue RuntimeError => e
|
||||
raise e unless e.message == 'no acceptor'
|
||||
raise RuntimeError.new("A server is already running on port #{@port}")
|
||||
end
|
||||
end
|
||||
|
||||
def stop
|
||||
thin.stop
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,152 +0,0 @@
|
||||
require 'enumerator'
|
||||
|
||||
module Jasmine
|
||||
class SpecBuilder
|
||||
attr_accessor :suites
|
||||
|
||||
def initialize(config)
|
||||
@config = config
|
||||
@spec_files = config.spec_files
|
||||
@runner = config
|
||||
@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
|
||||
@config.spec_files_full_paths.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 && Object.toJSON) { Object.toJSON(result) } 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 && Object.toJSON) { Object.toJSON(result) } 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
|
||||
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
http://www.JSON.org/json2.js
|
||||
2009-08-17
|
||||
|
||||
Public Domain.
|
||||
|
||||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
|
||||
See http://www.JSON.org/js.html
|
||||
|
||||
This file creates a global JSON object containing two methods: stringify
|
||||
and parse.
|
||||
|
||||
JSON.stringify(value, replacer, space)
|
||||
value any JavaScript value, usually an object or array.
|
||||
|
||||
replacer an optional parameter that determines how object
|
||||
values are stringified for objects. It can be a
|
||||
function or an array of strings.
|
||||
|
||||
space an optional parameter that specifies the indentation
|
||||
of nested structures. If it is omitted, the text will
|
||||
be packed without extra whitespace. If it is a number,
|
||||
it will specify the number of spaces to indent at each
|
||||
level. If it is a string (such as '\t' or ' '),
|
||||
it contains the characters used to indent at each level.
|
||||
|
||||
This method produces a JSON text from a JavaScript value.
|
||||
|
||||
When an object value is found, if the object contains a toJSON
|
||||
method, its toJSON method will be called and the result will be
|
||||
stringified. A toJSON method does not serialize: it returns the
|
||||
value represented by the name/value pair that should be serialized,
|
||||
or undefined if nothing should be serialized. The toJSON method
|
||||
will be passed the key associated with the value, and this will be
|
||||
bound to the value
|
||||
|
||||
For example, this would serialize Dates as ISO strings.
|
||||
|
||||
Date.prototype.toJSON = function (key) {
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10 ? '0' + n : n;
|
||||
}
|
||||
|
||||
return this.getUTCFullYear() + '-' +
|
||||
f(this.getUTCMonth() + 1) + '-' +
|
||||
f(this.getUTCDate()) + 'T' +
|
||||
f(this.getUTCHours()) + ':' +
|
||||
f(this.getUTCMinutes()) + ':' +
|
||||
f(this.getUTCSeconds()) + 'Z';
|
||||
};
|
||||
|
||||
You can provide an optional replacer method. It will be passed the
|
||||
key and value of each member, with this bound to the containing
|
||||
object. The value that is returned from your method will be
|
||||
serialized. If your method returns undefined, then the member will
|
||||
be excluded from the serialization.
|
||||
|
||||
If the replacer parameter is an array of strings, then it will be
|
||||
used to select the members to be serialized. It filters the results
|
||||
such that only members with keys listed in the replacer array are
|
||||
stringified.
|
||||
|
||||
Values that do not have JSON representations, such as undefined or
|
||||
functions, will not be serialized. Such values in objects will be
|
||||
dropped; in arrays they will be replaced with null. You can use
|
||||
a replacer function to replace those with JSON values.
|
||||
JSON.stringify(undefined) returns undefined.
|
||||
|
||||
The optional space parameter produces a stringification of the
|
||||
value that is filled with line breaks and indentation to make it
|
||||
easier to read.
|
||||
|
||||
If the space parameter is a non-empty string, then that string will
|
||||
be used for indentation. If the space parameter is a number, then
|
||||
the indentation will be that many spaces.
|
||||
|
||||
Example:
|
||||
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
||||
// text is '["e",{"pluribus":"unum"}]'
|
||||
|
||||
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
||||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
||||
|
||||
text = JSON.stringify([new Date()], function (key, value) {
|
||||
return this[key] instanceof Date ?
|
||||
'Date(' + this[key] + ')' : value;
|
||||
});
|
||||
// text is '["Date(---current time---)"]'
|
||||
|
||||
|
||||
JSON.parse(text, reviver)
|
||||
This method parses a JSON text to produce an object or array.
|
||||
It can throw a SyntaxError exception.
|
||||
|
||||
The optional reviver parameter is a function that can filter and
|
||||
transform the results. It receives each of the keys and values,
|
||||
and its return value is used instead of the original value.
|
||||
If it returns what it received, then the structure is not modified.
|
||||
If it returns undefined then the member is deleted.
|
||||
|
||||
Example:
|
||||
|
||||
// Parse the text. Values that look like ISO date strings will
|
||||
// be converted to Date objects.
|
||||
|
||||
myData = JSON.parse(text, function (key, value) {
|
||||
var a;
|
||||
if (typeof value === 'string') {
|
||||
a =
|
||||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
||||
if (a) {
|
||||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
||||
+a[5], +a[6]));
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
||||
var d;
|
||||
if (typeof value === 'string' &&
|
||||
value.slice(0, 5) === 'Date(' &&
|
||||
value.slice(-1) === ')') {
|
||||
d = new Date(value.slice(5, -1));
|
||||
if (d) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
|
||||
This is a reference implementation. You are free to copy, modify, or
|
||||
redistribute.
|
||||
|
||||
This code should be minified before deployment.
|
||||
See http://javascript.crockford.com/jsmin.html
|
||||
|
||||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
||||
NOT CONTROL.
|
||||
*/
|
||||
|
||||
/*jslint evil: true */
|
||||
|
||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
||||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
||||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
||||
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
||||
test, toJSON, toString, valueOf
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
// Create a JSON object only if one does not already exist. We create the
|
||||
// methods in a closure to avoid creating global variables.
|
||||
|
||||
if (!this.JSON) {
|
||||
this.JSON = {};
|
||||
}
|
||||
|
||||
(function () {
|
||||
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10 ? '0' + n : n;
|
||||
}
|
||||
|
||||
if (typeof Date.prototype.toJSON !== 'function') {
|
||||
|
||||
Date.prototype.toJSON = function (key) {
|
||||
|
||||
return isFinite(this.valueOf()) ?
|
||||
this.getUTCFullYear() + '-' +
|
||||
f(this.getUTCMonth() + 1) + '-' +
|
||||
f(this.getUTCDate()) + 'T' +
|
||||
f(this.getUTCHours()) + ':' +
|
||||
f(this.getUTCMinutes()) + ':' +
|
||||
f(this.getUTCSeconds()) + 'Z' : null;
|
||||
};
|
||||
|
||||
String.prototype.toJSON =
|
||||
Number.prototype.toJSON =
|
||||
Boolean.prototype.toJSON = function (key) {
|
||||
return this.valueOf();
|
||||
};
|
||||
}
|
||||
|
||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
gap,
|
||||
indent,
|
||||
meta = { // table of character substitutions
|
||||
'\b': '\\b',
|
||||
'\t': '\\t',
|
||||
'\n': '\\n',
|
||||
'\f': '\\f',
|
||||
'\r': '\\r',
|
||||
'"' : '\\"',
|
||||
'\\': '\\\\'
|
||||
},
|
||||
rep;
|
||||
|
||||
|
||||
function quote(string) {
|
||||
|
||||
// If the string contains no control characters, no quote characters, and no
|
||||
// backslash characters, then we can safely slap some quotes around it.
|
||||
// Otherwise we must also replace the offending characters with safe escape
|
||||
// sequences.
|
||||
|
||||
escapable.lastIndex = 0;
|
||||
return escapable.test(string) ?
|
||||
'"' + string.replace(escapable, function (a) {
|
||||
var c = meta[a];
|
||||
return typeof c === 'string' ? c :
|
||||
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
}) + '"' :
|
||||
'"' + string + '"';
|
||||
}
|
||||
|
||||
|
||||
function str(key, holder) {
|
||||
// Produce a string from holder[key].
|
||||
|
||||
var i, // The loop counter.
|
||||
k, // The member key.
|
||||
v, // The member value.
|
||||
length,
|
||||
mind = gap,
|
||||
partial,
|
||||
value = holder[key];
|
||||
|
||||
// If the value has a toJSON method, call it to obtain a replacement value.
|
||||
|
||||
if (value && typeof value === 'object' &&
|
||||
typeof value.toJSON === 'function') {
|
||||
value = value.toJSON(key);
|
||||
}
|
||||
|
||||
// If we were called with a replacer function, then call the replacer to
|
||||
// obtain a replacement value.
|
||||
|
||||
if (typeof rep === 'function') {
|
||||
value = rep.call(holder, key, value);
|
||||
}
|
||||
|
||||
// What happens next depends on the value's type.
|
||||
|
||||
switch (typeof value) {
|
||||
case 'string':
|
||||
return quote(value);
|
||||
|
||||
case 'number':
|
||||
|
||||
// JSON numbers must be finite. Encode non-finite numbers as null.
|
||||
|
||||
return isFinite(value) ? String(value) : 'null';
|
||||
|
||||
case 'boolean':
|
||||
case 'null':
|
||||
|
||||
// If the value is a boolean or null, convert it to a string. Note:
|
||||
// typeof null does not produce 'null'. The case is included here in
|
||||
// the remote chance that this gets fixed someday.
|
||||
|
||||
return String(value);
|
||||
|
||||
// If the type is 'object', we might be dealing with an object or an array or
|
||||
// null.
|
||||
|
||||
case 'object':
|
||||
|
||||
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
||||
// so watch out for that case.
|
||||
|
||||
if (!value) {
|
||||
return 'null';
|
||||
}
|
||||
|
||||
// Make an array to hold the partial results of stringifying this object value.
|
||||
|
||||
gap += indent;
|
||||
partial = [];
|
||||
|
||||
// Is the value an array?
|
||||
|
||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
||||
|
||||
// The value is an array. Stringify every element. Use null as a placeholder
|
||||
// for non-JSON values.
|
||||
|
||||
length = value.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
partial[i] = str(i, value) || 'null';
|
||||
}
|
||||
|
||||
// Join all of the elements together, separated with commas, and wrap them in
|
||||
// brackets.
|
||||
|
||||
v = partial.length === 0 ? '[]' :
|
||||
gap ? '[\n' + gap +
|
||||
partial.join(',\n' + gap) + '\n' +
|
||||
mind + ']' :
|
||||
'[' + partial.join(',') + ']';
|
||||
gap = mind;
|
||||
return v;
|
||||
}
|
||||
|
||||
// If the replacer is an array, use it to select the members to be stringified.
|
||||
|
||||
if (rep && typeof rep === 'object') {
|
||||
length = rep.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
k = rep[i];
|
||||
if (typeof k === 'string') {
|
||||
v = str(k, value);
|
||||
if (v) {
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// Otherwise, iterate through all of the keys in the object.
|
||||
|
||||
for (k in value) {
|
||||
if (Object.hasOwnProperty.call(value, k)) {
|
||||
v = str(k, value);
|
||||
if (v) {
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Join all of the member texts together, separated with commas,
|
||||
// and wrap them in braces.
|
||||
|
||||
v = partial.length === 0 ? '{}' :
|
||||
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
||||
mind + '}' : '{' + partial.join(',') + '}';
|
||||
gap = mind;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
// If the JSON object does not yet have a stringify method, give it one.
|
||||
|
||||
if (typeof JSON.stringify !== 'function') {
|
||||
JSON.stringify = function (value, replacer, space) {
|
||||
// The stringify method takes a value and an optional replacer, and an optional
|
||||
// space parameter, and returns a JSON text. The replacer can be a function
|
||||
// that can replace values, or an array of strings that will select the keys.
|
||||
// A default replacer method can be provided. Use of the space parameter can
|
||||
// produce text that is more easily readable.
|
||||
|
||||
var i;
|
||||
gap = '';
|
||||
indent = '';
|
||||
|
||||
// If the space parameter is a number, make an indent string containing that
|
||||
// many spaces.
|
||||
|
||||
if (typeof space === 'number') {
|
||||
for (i = 0; i < space; i += 1) {
|
||||
indent += ' ';
|
||||
}
|
||||
|
||||
// If the space parameter is a string, it will be used as the indent string.
|
||||
|
||||
} else if (typeof space === 'string') {
|
||||
indent = space;
|
||||
}
|
||||
|
||||
// If there is a replacer, it must be a function or an array.
|
||||
// Otherwise, throw an error.
|
||||
|
||||
rep = replacer;
|
||||
if (replacer && typeof replacer !== 'function' &&
|
||||
(typeof replacer !== 'object' ||
|
||||
typeof replacer.length !== 'number')) {
|
||||
throw new Error('JSON.stringify');
|
||||
}
|
||||
|
||||
// Make a fake root object containing our value under the key of ''.
|
||||
// Return the result of stringifying the value.
|
||||
|
||||
return str('', {'': value});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// If the JSON object does not yet have a parse method, give it one.
|
||||
|
||||
if (typeof JSON.parse !== 'function') {
|
||||
JSON.parse = function (text, reviver) {
|
||||
|
||||
// The parse method takes a text and an optional reviver function, and returns
|
||||
// a JavaScript value if the text is a valid JSON text.
|
||||
|
||||
var j;
|
||||
|
||||
function walk(holder, key) {
|
||||
|
||||
// The walk method is used to recursively walk the resulting structure so
|
||||
// that modifications can be made.
|
||||
|
||||
var k, v, value = holder[key];
|
||||
if (value && typeof value === 'object') {
|
||||
for (k in value) {
|
||||
if (Object.hasOwnProperty.call(value, k)) {
|
||||
v = walk(value, k);
|
||||
if (v !== undefined) {
|
||||
value[k] = v;
|
||||
} else {
|
||||
delete value[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return reviver.call(holder, key, value);
|
||||
}
|
||||
|
||||
|
||||
// Parsing happens in four stages. In the first stage, we replace certain
|
||||
// Unicode characters with escape sequences. JavaScript handles many characters
|
||||
// incorrectly, either silently deleting them, or treating them as line endings.
|
||||
|
||||
cx.lastIndex = 0;
|
||||
if (cx.test(text)) {
|
||||
text = text.replace(cx, function (a) {
|
||||
return '\\u' +
|
||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
});
|
||||
}
|
||||
|
||||
// In the second stage, we run the text against regular expressions that look
|
||||
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
||||
// because they can cause invocation, and '=' because it can cause mutation.
|
||||
// But just to be safe, we want to reject all unexpected forms.
|
||||
|
||||
// We split the second stage into 4 regexp operations in order to work around
|
||||
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
||||
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
||||
// replace all simple value tokens with ']' characters. Third, we delete all
|
||||
// open brackets that follow a colon or comma or that begin the text. Finally,
|
||||
// we look to see that the remaining characters are only whitespace or ']' or
|
||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
||||
|
||||
if (/^[\],:{}\s]*$/.
|
||||
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
|
||||
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
||||
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||
|
||||
// In the third stage we use the eval function to compile the text into a
|
||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
||||
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
||||
// in parens to eliminate the ambiguity.
|
||||
|
||||
j = eval('(' + text + ')');
|
||||
|
||||
// In the optional fourth stage, we recursively walk the new structure, passing
|
||||
// each name/value pair to a reviver function for possible transformation.
|
||||
|
||||
return typeof reviver === 'function' ?
|
||||
walk({'': j}, '') : j;
|
||||
}
|
||||
|
||||
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
||||
|
||||
throw new SyntaxError('JSON.parse');
|
||||
};
|
||||
}
|
||||
}());
|
||||
@@ -1,113 +0,0 @@
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
||||
|
||||
describe Jasmine::Config do
|
||||
before(:each) do
|
||||
@template_dir = File.expand_path(File.join(File.dirname(__FILE__), "../generators/jasmine/templates"))
|
||||
@config = Jasmine::Config.new
|
||||
end
|
||||
|
||||
describe "configuration" do
|
||||
before(:each) do
|
||||
@config.stub!(:src_dir).and_return(File.join(@template_dir, "public"))
|
||||
@config.stub!(:spec_dir).and_return(File.join(@template_dir, "spec"))
|
||||
end
|
||||
|
||||
it "if sources.yaml not found" do
|
||||
File.stub!(:exist?).and_return(false)
|
||||
@config.src_files.should == []
|
||||
@config.stylesheets.should == []
|
||||
@config.spec_files.should == ['javascripts/ExampleSpec.js', 'javascripts/SpecHelper.js']
|
||||
@config.mappings.should == {
|
||||
'/__root__' => @config.project_root,
|
||||
'/__spec__' => @config.spec_dir
|
||||
}
|
||||
end
|
||||
|
||||
it "if jasmine.yml is empty" do
|
||||
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine.yml'))
|
||||
YAML.stub!(:load).and_return(false)
|
||||
@config.src_files.should == []
|
||||
@config.stylesheets.should == []
|
||||
@config.spec_files.should == ['javascripts/ExampleSpec.js', 'javascripts/SpecHelper.js']
|
||||
@config.mappings.should == {
|
||||
'/__root__' => @config.project_root,
|
||||
'/__spec__' => @config.spec_dir
|
||||
}
|
||||
end
|
||||
|
||||
it "using default jasmine.yml" do
|
||||
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine.yml'))
|
||||
@config.src_files.should == []
|
||||
@config.spec_files.should == ['javascripts/ExampleSpec.js', 'javascripts/SpecHelper.js']
|
||||
@config.mappings.should == {
|
||||
'/__root__' => @config.project_root,
|
||||
'/__spec__' => @config.spec_dir
|
||||
}
|
||||
end
|
||||
|
||||
it "simple_config stylesheets" do
|
||||
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine.yml'))
|
||||
YAML.stub!(:load).and_return({'stylesheets' => ['foo.css', 'bar.css']})
|
||||
Dir.stub!(:glob).and_return do |glob_string|
|
||||
glob_string
|
||||
end
|
||||
@config.stylesheets.should == ['foo.css', 'bar.css']
|
||||
end
|
||||
|
||||
it "using rails jasmine.yml" do
|
||||
original_glob = Dir.method(:glob)
|
||||
Dir.stub!(:glob).and_return do |glob_string|
|
||||
if glob_string =~ /public/
|
||||
glob_string
|
||||
else
|
||||
original_glob.call(glob_string)
|
||||
end
|
||||
end
|
||||
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine-rails.yml'))
|
||||
@config.spec_files.should == ['javascripts/ExampleSpec.js', 'javascripts/SpecHelper.js']
|
||||
@config.src_files.should == ['javascripts/prototype.js',
|
||||
'javascripts/effects.js',
|
||||
'javascripts/controls.js',
|
||||
'javascripts/dragdrop.js',
|
||||
'javascripts/application.js']
|
||||
@config.js_files.should == [
|
||||
'/javascripts/prototype.js',
|
||||
'/javascripts/effects.js',
|
||||
'/javascripts/controls.js',
|
||||
'/javascripts/dragdrop.js',
|
||||
'/javascripts/application.js',
|
||||
'/__spec__/javascripts/ExampleSpec.js',
|
||||
'/__spec__/javascripts/SpecHelper.js',
|
||||
]
|
||||
end
|
||||
|
||||
it "should provide a list of all spec files with full paths" do
|
||||
@config.spec_files_full_paths.should == [
|
||||
File.join(@template_dir, 'spec/javascripts/ExampleSpec.js'),
|
||||
File.join(@template_dir, 'spec/javascripts/SpecHelper.js')
|
||||
]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
it "src_dir uses root when src dir is blank" do
|
||||
@config.stub!(:project_root).and_return('some_project_root')
|
||||
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine.yml'))
|
||||
YAML.stub!(:load).and_return({'src_dir' => nil})
|
||||
@config.src_dir.should == 'some_project_root'
|
||||
end
|
||||
|
||||
it "should use correct default yaml config" do
|
||||
@config.stub!(:project_root).and_return('some_project_root')
|
||||
@config.simple_config_file.should == (File.join('some_project_root', 'spec/javascripts/support/jasmine.yml'))
|
||||
end
|
||||
|
||||
|
||||
it "should provide dir mappings" do
|
||||
@config.mappings.should == {
|
||||
'/__root__' => @config.project_root,
|
||||
'/__spec__' => @config.spec_dir
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,15 +0,0 @@
|
||||
require 'jasmine'
|
||||
|
||||
class JasmineSelfTestConfig < Jasmine::Config
|
||||
def project_root
|
||||
File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
||||
end
|
||||
|
||||
def src_dir
|
||||
File.join(project_root, 'src')
|
||||
end
|
||||
|
||||
def spec_dir
|
||||
File.join(project_root, 'jasmine/spec')
|
||||
end
|
||||
end
|
||||
@@ -1,18 +0,0 @@
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
||||
|
||||
require 'jasmine_self_test_config'
|
||||
|
||||
jasmine_config = JasmineSelfTestConfig.new
|
||||
spec_builder = Jasmine::SpecBuilder.new(jasmine_config)
|
||||
|
||||
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
|
||||
@@ -0,0 +1,80 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Jasmine Test Runner</title>
|
||||
|
||||
<script type="text/javascript">
|
||||
// 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>
|
||||
<script type="text/javascript" src="../src/MultiReporter.js"></script>
|
||||
<script type="text/javascript" src="../src/NestedResults.js"></script>
|
||||
<script type="text/javascript" src="../src/PrettyPrinter.js"></script>
|
||||
<script type="text/javascript" src="../src/Queue.js"></script>
|
||||
<script type="text/javascript" src="../src/Runner.js"></script>
|
||||
<script type="text/javascript" src="../src/Spec.js"></script>
|
||||
<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="../src/html/TrivialReporter.js"></script>
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript" src="suites/BaseSpec.js"></script>
|
||||
<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/MockClockSpec.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;
|
||||
|
||||
var trivialReporter = new jasmine.TrivialReporter();
|
||||
|
||||
jasmineEnv.addReporter(trivialReporter);
|
||||
|
||||
jasmineEnv.specFilter = function(spec) {
|
||||
return trivialReporter.specFilter(spec);
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
jasmineEnv.execute();
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
|
||||
<link href="../src/html/jasmine.css" rel="stylesheet"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,73 +0,0 @@
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
||||
|
||||
def read(body)
|
||||
return body if body.is_a?(String)
|
||||
out = ""
|
||||
body.each {|data| out += data }
|
||||
out
|
||||
end
|
||||
|
||||
describe Jasmine::Server do
|
||||
before(:each) do
|
||||
config = Jasmine::Config.new
|
||||
config.stub!(:mappings).and_return({
|
||||
"/src" => File.join(Jasmine.root, "src"),
|
||||
"/spec" => File.join(Jasmine.root, "spec")
|
||||
})
|
||||
|
||||
config.stub!(:js_files).and_return(["/src/file1.js", "/spec/file2.js"])
|
||||
|
||||
@server = Jasmine::Server.new(0, config)
|
||||
@thin_app = @server.thin.app
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
@server.thin.stop if @server && @server.thin.running?
|
||||
end
|
||||
|
||||
it "should serve static files" do
|
||||
code, headers, body = @thin_app.call("PATH_INFO" => "/spec/suites/EnvSpec.js", "SCRIPT_NAME" => "xxx")
|
||||
code.should == 200
|
||||
headers["Content-Type"].should == "application/javascript"
|
||||
read(body).should == File.read(File.join(Jasmine.root, "spec/suites/EnvSpec.js"))
|
||||
end
|
||||
|
||||
it "should serve Jasmine static files under /__JASMINE_ROOT__/" do
|
||||
code, headers, body = @thin_app.call("PATH_INFO" => "/__JASMINE_ROOT__/lib/jasmine.css", "SCRIPT_NAME" => "xxx")
|
||||
code.should == 200
|
||||
headers["Content-Type"].should == "text/css"
|
||||
read(body).should == File.read(File.join(Jasmine.root, "lib/jasmine.css"))
|
||||
end
|
||||
|
||||
it "should redirect /run.html to /" do
|
||||
code, headers, body = @thin_app.call("PATH_INFO" => "/run.html", "SCRIPT_NAME" => "xxx")
|
||||
code.should == 302
|
||||
headers["Location"].should == "/"
|
||||
end
|
||||
|
||||
it "should 404 non-existent files" do
|
||||
code, headers, body = @thin_app.call("PATH_INFO" => "/some-non-existent-file", "SCRIPT_NAME" => "xxx")
|
||||
code.should == 404
|
||||
|
||||
end
|
||||
|
||||
describe "/ page" do
|
||||
it "should load each js file in order" do
|
||||
code, headers, body = @thin_app.call("PATH_INFO" => "/", "SCRIPT_NAME" => "xxx", "REQUEST_METHOD" => 'GET')
|
||||
code.should == 200
|
||||
body = read(body)
|
||||
body.should include("\"/src/file1.js")
|
||||
body.should include("\"/spec/file2.js")
|
||||
body.should satisfy {|s| s.index("/src/file1.js") < s.index("/spec/file2.js") }
|
||||
end
|
||||
|
||||
it "should return an empty 200 for HEAD requests to /" do
|
||||
code, headers, body = @thin_app.call("PATH_INFO" => "/", "SCRIPT_NAME" => "xxx", "REQUEST_METHOD" => 'HEAD')
|
||||
code.should == 200
|
||||
headers.should == { 'Content-Type' => 'text/html' }
|
||||
body.should == ''
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,3 +0,0 @@
|
||||
require 'spec'
|
||||
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), "../lib/jasmine"))
|
||||
@@ -0,0 +1,27 @@
|
||||
describe("base.js", function() {
|
||||
describe("jasmine.MessageResult", function() {
|
||||
it("#toString should pretty-print and concatenate each part of the message", function() {
|
||||
var values = ["log", "message", 123, {key: "value"}, "FTW!"];
|
||||
var messageResult = new jasmine.MessageResult(values);
|
||||
expect(messageResult.toString()).toEqual("log message 123 { key : 'value' } FTW!");
|
||||
});
|
||||
});
|
||||
|
||||
describe("jasmine.log", function() {
|
||||
it("should accept n arguments", function() {
|
||||
spyOn(jasmine.getEnv().currentSpec, 'log');
|
||||
jasmine.log(1, 2, 3);
|
||||
expect(jasmine.getEnv().currentSpec.log).toHaveBeenCalledWith(1, 2, 3);
|
||||
});
|
||||
});
|
||||
|
||||
describe("jasmine.getGlobal", function() {
|
||||
it("should return the global object", function() {
|
||||
var globalObject = (function() {
|
||||
return this;
|
||||
})();
|
||||
|
||||
expect(jasmine.getGlobal()).toBe(globalObject);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
describe("Custom Matchers", function() {
|
||||
var env;
|
||||
var fakeTimer;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmine.Env();
|
||||
env.updateInterval = 0;
|
||||
});
|
||||
|
||||
it("should be easy to add more matchers local to a spec, suite, etc.", function() {
|
||||
var spec1, spec2, spec1Matcher, spec2Matcher;
|
||||
var suite = env.describe('some suite', function() {
|
||||
env.beforeEach(function() {
|
||||
this.addMatchers({
|
||||
matcherForSuite: function(expected) {
|
||||
this.message = "matcherForSuite: actual: " + this.actual + "; expected: " + expected;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
spec1 = env.it('spec with an expectation').runs(function () {
|
||||
this.addMatchers({
|
||||
matcherForSpec: function(expected) {
|
||||
this.message = "matcherForSpec: actual: " + this.actual + "; expected: " + expected;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
spec1Matcher = this.expect("xxx");
|
||||
});
|
||||
|
||||
spec2 = env.it('spec with failing expectation').runs(function () {
|
||||
spec2Matcher = this.expect("yyy");
|
||||
});
|
||||
});
|
||||
|
||||
suite.execute();
|
||||
|
||||
spec1Matcher.matcherForSuite("expected");
|
||||
expect(spec1Matcher.message).toEqual("matcherForSuite: actual: xxx; expected: expected");
|
||||
spec1Matcher.matcherForSpec("expected");
|
||||
expect(spec1Matcher.message).toEqual("matcherForSpec: actual: xxx; expected: expected");
|
||||
|
||||
spec2Matcher.matcherForSuite("expected");
|
||||
expect(spec2Matcher.message).toEqual("matcherForSuite: actual: yyy; expected: expected");
|
||||
expect(spec2Matcher.matcherForSpec).toBe(jasmine.undefined);
|
||||
});
|
||||
|
||||
it("should generate messages with the same rules as for regular matchers when this.report() is not called", function() {
|
||||
var spec;
|
||||
var suite = env.describe('some suite', function() {
|
||||
spec = env.it('spec with an expectation').runs(function () {
|
||||
this.addMatchers({
|
||||
toBeTrue: function() {
|
||||
return this.actual === true;
|
||||
}
|
||||
});
|
||||
this.expect(true).toBeTrue();
|
||||
this.expect(false).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
suite.execute();
|
||||
var passResult = new jasmine.ExpectationResult({passed: true, matcherName: 'toBeTrue',
|
||||
actual: true, expected: jasmine.undefined, message: "Passed." });
|
||||
var failResult = new jasmine.ExpectationResult({passed: false, matcherName: 'toBeTrue',
|
||||
actual: false, expected: jasmine.undefined, message: "Expected false to be true." });
|
||||
failResult.trace = jasmine.any(Object);
|
||||
expect(spec.results().getItems()).toEqual([passResult, failResult]);
|
||||
});
|
||||
|
||||
it("should pass args", function() {
|
||||
var matcherCallArgs = [];
|
||||
var spec;
|
||||
var suite = env.describe('some suite', function() {
|
||||
spec = env.it('spec with an expectation').runs(function () {
|
||||
this.addMatchers({
|
||||
toBeTrue: function() {
|
||||
matcherCallArgs.push(jasmine.util.argsToArray(arguments));
|
||||
return this.actual === true;
|
||||
}
|
||||
});
|
||||
this.expect(true).toBeTrue();
|
||||
this.expect(false).toBeTrue('arg');
|
||||
this.expect(true).toBeTrue('arg1', 'arg2');
|
||||
});
|
||||
});
|
||||
|
||||
suite.execute();
|
||||
var results = spec.results().getItems();
|
||||
expect(results[0].expected).toEqual(jasmine.undefined);
|
||||
expect(results[1].expected).toEqual('arg');
|
||||
expect(results[2].expected).toEqual(['arg1', 'arg2']);
|
||||
|
||||
expect(matcherCallArgs).toEqual([[], ['arg'], ['arg1', 'arg2']]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,158 @@
|
||||
describe("jasmine.Env", function() {
|
||||
var env;
|
||||
beforeEach(function() {
|
||||
env = new jasmine.Env();
|
||||
env.updateInterval = 0;
|
||||
});
|
||||
|
||||
describe('ids', function () {
|
||||
it('nextSpecId should return consecutive integers, starting at 0', function () {
|
||||
expect(env.nextSpecId()).toEqual(0);
|
||||
expect(env.nextSpecId()).toEqual(1);
|
||||
expect(env.nextSpecId()).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("reporting", function() {
|
||||
var fakeReporter;
|
||||
|
||||
beforeEach(function() {
|
||||
fakeReporter = jasmine.createSpyObj("fakeReporter", ["log"]);
|
||||
});
|
||||
|
||||
describe('version', function () {
|
||||
var oldVersion;
|
||||
|
||||
beforeEach(function () {
|
||||
oldVersion = jasmine.version_;
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
jasmine.version_ = oldVersion;
|
||||
});
|
||||
|
||||
it('should raise an error if version is not set', function () {
|
||||
jasmine.version_ = null;
|
||||
var exception;
|
||||
try {
|
||||
env.version();
|
||||
}
|
||||
catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
expect(exception.message).toEqual('Version not set');
|
||||
});
|
||||
|
||||
it("version should return the current version as an int", function() {
|
||||
jasmine.version_ = {
|
||||
"major": 1,
|
||||
"minor": 9,
|
||||
"build": 7,
|
||||
"revision": 8
|
||||
};
|
||||
expect(env.version()).toEqual({
|
||||
"major": 1,
|
||||
"minor": 9,
|
||||
"build": 7,
|
||||
"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() {
|
||||
env.addReporter(fakeReporter);
|
||||
env.reporter.log("message");
|
||||
expect(fakeReporter.log).toHaveBeenCalledWith("message");
|
||||
});
|
||||
});
|
||||
|
||||
describe("equality testing", function() {
|
||||
describe("with custom equality testers", function() {
|
||||
var aObj, bObj, isEqual;
|
||||
|
||||
beforeEach(function() {
|
||||
env.addEqualityTester(function(a, b) {
|
||||
aObj = a;
|
||||
bObj = b;
|
||||
return isEqual;
|
||||
});
|
||||
});
|
||||
|
||||
it("should call the custom equality tester with two objects for comparison", function() {
|
||||
env.equals_("1", "2");
|
||||
expect(aObj).toEqual("1");
|
||||
expect(bObj).toEqual("2");
|
||||
});
|
||||
|
||||
describe("when the custom equality tester returns false", function() {
|
||||
beforeEach(function() {
|
||||
isEqual = false;
|
||||
});
|
||||
|
||||
it("should give custom equality testers precedence", function() {
|
||||
expect(env.equals_('abc', 'abc')).toBeFalsy();
|
||||
var o = new Object();
|
||||
expect(env.equals_(o, o)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("when the custom equality tester returns true", function() {
|
||||
beforeEach(function() {
|
||||
isEqual = true;
|
||||
});
|
||||
|
||||
it("should give custom equality testers precedence", function() {
|
||||
expect(env.equals_('abc', 'def')).toBeTruthy();
|
||||
expect(env.equals_(true, false)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the custom equality tester returns undefined", function() {
|
||||
beforeEach(function() {
|
||||
isEqual = jasmine.undefined;
|
||||
});
|
||||
|
||||
it("should use normal equality rules", function() {
|
||||
expect(env.equals_('abc', 'abc')).toBeTruthy();
|
||||
expect(env.equals_('abc', 'def')).toBeFalsy();
|
||||
});
|
||||
|
||||
describe("even if there are several", function() {
|
||||
beforeEach(function() {
|
||||
env.addEqualityTester(function(a, b) { return jasmine.undefined; });
|
||||
env.addEqualityTester(function(a, b) { return jasmine.undefined; });
|
||||
});
|
||||
|
||||
it("should use normal equality rules", function() {
|
||||
expect(env.equals_('abc', 'abc')).toBeTruthy();
|
||||
expect(env.equals_('abc', 'def')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should evaluate custom equality testers in the order they are declared", function() {
|
||||
isEqual = false;
|
||||
env.addEqualityTester(function(a, b) { return true; });
|
||||
expect(env.equals_('abc', 'abc')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,107 @@
|
||||
describe('Exceptions:', function() {
|
||||
var env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmine.Env();
|
||||
env.updateInterval = 0;
|
||||
});
|
||||
|
||||
it('jasmine.formatException formats Firefox exception messages as expected', function() {
|
||||
var sampleFirefoxException = {
|
||||
fileName: 'foo.js',
|
||||
line: '1978',
|
||||
message: 'you got your foo in my bar',
|
||||
name: 'A Classic Mistake'
|
||||
};
|
||||
|
||||
var expected = 'A Classic Mistake: you got your foo in my bar in foo.js (line 1978)';
|
||||
|
||||
expect(jasmine.util.formatException(sampleFirefoxException)).toEqual(expected);
|
||||
});
|
||||
|
||||
it('jasmine.formatException formats Webkit exception messages as expected', function() {
|
||||
var sampleWebkitException = {
|
||||
sourceURL: 'foo.js',
|
||||
lineNumber: '1978',
|
||||
message: 'you got your foo in my bar',
|
||||
name: 'A Classic Mistake'
|
||||
};
|
||||
|
||||
var expected = 'A Classic Mistake: you got your foo in my bar in foo.js (line 1978)';
|
||||
|
||||
expect(jasmine.util.formatException(sampleWebkitException)).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should handle exceptions thrown, but continue', function() {
|
||||
var fakeTimer = new jasmine.FakeTimer();
|
||||
env.setTimeout = fakeTimer.setTimeout;
|
||||
env.clearTimeout = fakeTimer.clearTimeout;
|
||||
env.setInterval = fakeTimer.setInterval;
|
||||
env.clearInterval = fakeTimer.clearInterval;
|
||||
|
||||
//we run two exception tests to make sure we continue after throwing an exception
|
||||
var suite = env.describe('Suite for handles exceptions', function () {
|
||||
env.it('should be a test that fails because it throws an exception', function() {
|
||||
throw new Error('fake error 1');
|
||||
});
|
||||
|
||||
env.it('should be another test that fails because it throws an exception', function() {
|
||||
this.runs(function () {
|
||||
throw new Error('fake error 2');
|
||||
});
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
env.it('should be a passing test that runs after exceptions are thrown', function() {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
|
||||
env.it('should be another test that fails because it throws an exception after a wait', function() {
|
||||
this.runs(function () {
|
||||
var foo = 'foo';
|
||||
});
|
||||
this.waits(250);
|
||||
this.runs(function () {
|
||||
throw new Error('fake error 3');
|
||||
});
|
||||
});
|
||||
|
||||
env.it('should be a passing test that runs after exceptions are thrown from a async test', function() {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
var runner = env.currentRunner();
|
||||
suite.execute();
|
||||
fakeTimer.tick(2500);
|
||||
|
||||
var suiteResults = suite.results();
|
||||
var specResults = suiteResults.getItems();
|
||||
|
||||
expect(suiteResults.passed()).toEqual(false);
|
||||
//
|
||||
expect(specResults.length).toEqual(5);
|
||||
expect(specResults[0].passed()).toMatch(false);
|
||||
var blockResults = specResults[0].getItems();
|
||||
expect(blockResults[0].passed()).toEqual(false);
|
||||
expect(blockResults[0].message).toMatch(/fake error 1/);
|
||||
|
||||
expect(specResults[1].passed()).toEqual(false);
|
||||
var blockResults = specResults[1].getItems();
|
||||
expect(blockResults[0].passed()).toEqual(false);
|
||||
expect(blockResults[0].message).toMatch(/fake error 2/),
|
||||
expect(blockResults[1].passed()).toEqual(true);
|
||||
|
||||
expect(specResults[2].passed()).toEqual(true);
|
||||
|
||||
expect(specResults[3].passed()).toEqual(false);
|
||||
blockResults = specResults[3].getItems();
|
||||
expect(blockResults[0].message).toMatch(/fake error 3/);
|
||||
|
||||
expect(specResults[4].passed()).toEqual(true);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,103 @@
|
||||
describe('jasmine.jsApiReporter', function() {
|
||||
describe('results', function () {
|
||||
var reporter, spec1, spec2, spec3, expectedSpec1Results, expectedSpec2Results;
|
||||
var env;
|
||||
var suite, nestedSuite, nestedSpec;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmine.Env();
|
||||
env.updateInterval = 0;
|
||||
|
||||
suite = env.describe("top-level suite", function() {
|
||||
spec1 = env.it("spec 1", function() {
|
||||
this.expect(true).toEqual(true);
|
||||
|
||||
});
|
||||
|
||||
spec2 = env.it("spec 2", function() {
|
||||
this.expect(true).toEqual(false);
|
||||
});
|
||||
|
||||
nestedSuite = env.describe("nested suite", function() {
|
||||
nestedSpec = env.it("nested spec", function() {
|
||||
expect(true).toEqual(true);
|
||||
})
|
||||
});
|
||||
|
||||
spec3 = env.it("spec 3", function() {
|
||||
this.log('some debug message');
|
||||
});
|
||||
});
|
||||
|
||||
reporter = new jasmine.JsApiReporter();
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.execute();
|
||||
|
||||
expectedSpec1Results = {
|
||||
messages: spec1.results().getItems(),
|
||||
result: "passed"
|
||||
};
|
||||
expectedSpec2Results = {
|
||||
messages: spec2.results().getItems(),
|
||||
result: "failed"
|
||||
};
|
||||
});
|
||||
|
||||
it('resultForSpec() should return the result for the given spec', function () {
|
||||
expect(reporter.resultsForSpec(spec1.id)).toEqual(expectedSpec1Results);
|
||||
expect(reporter.resultsForSpec(spec2.id)).toEqual(expectedSpec2Results);
|
||||
});
|
||||
|
||||
it('results() should return a hash of all results, indexed by spec id', function () {
|
||||
expect(reporter.results()[spec1.id]).toEqual(expectedSpec1Results);
|
||||
expect(reporter.results()[spec2.id]).toEqual(expectedSpec2Results);
|
||||
});
|
||||
|
||||
it("should return nested suites as children of their parents", function() {
|
||||
expect(reporter.suites()).toEqual([
|
||||
{ id: 0, name: 'top-level suite', type: 'suite',
|
||||
children: [
|
||||
{ id: 0, name: 'spec 1', type: 'spec', children: [ ] },
|
||||
{ id: 1, name: 'spec 2', type: 'spec', children: [ ] },
|
||||
{ id: 1, name: 'nested suite', type: 'suite',
|
||||
children: [
|
||||
{ id: 2, name: 'nested spec', type: 'spec', children: [ ] }
|
||||
]
|
||||
},
|
||||
{ id: 3, name: 'spec 3', type: 'spec', children: [ ] }
|
||||
]
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
describe("#summarizeResult_", function() {
|
||||
it("should summarize a passing result", function() {
|
||||
var result = reporter.results()[spec1.id];
|
||||
var summarizedResult = reporter.summarizeResult_(result);
|
||||
expect(summarizedResult.result).toEqual('passed');
|
||||
expect(summarizedResult.messages.length).toEqual(1);
|
||||
expect(summarizedResult.messages[0].message).toEqual(result.messages[0].message);
|
||||
expect(summarizedResult.messages[0].passed).toBeTruthy();
|
||||
expect(summarizedResult.messages[0].type).toEqual('expect');
|
||||
expect(summarizedResult.messages[0].text).toBeUndefined();
|
||||
expect(summarizedResult.messages[0].trace.stack).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should have a stack trace for failing specs", function() {
|
||||
var result = reporter.results()[spec2.id];
|
||||
var summarizedResult = reporter.summarizeResult_(result);
|
||||
expect(summarizedResult.result).toEqual('failed');
|
||||
expect(summarizedResult.messages[0].trace.stack).toEqual(result.messages[0].trace.stack);
|
||||
});
|
||||
|
||||
it("should have messages for specs with messages", function() {
|
||||
var result = reporter.results()[spec3.id];
|
||||
var summarizedResult = reporter.summarizeResult_(result);
|
||||
expect(summarizedResult.result).toEqual('passed');
|
||||
expect(summarizedResult.messages[0].type).toEqual('log');
|
||||
expect(summarizedResult.messages[0].text).toEqual('some debug message');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,795 @@
|
||||
describe("jasmine.Matchers", function() {
|
||||
var env, spec;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmine.Env();
|
||||
env.updateInterval = 0;
|
||||
|
||||
var suite = env.describe("suite", function() {
|
||||
spec = env.it("spec", function() {
|
||||
});
|
||||
});
|
||||
spyOn(spec, 'addMatcherResult');
|
||||
|
||||
this.addMatchers({
|
||||
toPass: function() {
|
||||
return lastResult().passed();
|
||||
},
|
||||
toFail: function() {
|
||||
return !lastResult().passed();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function match(value) {
|
||||
return spec.expect(value);
|
||||
}
|
||||
|
||||
function lastResult() {
|
||||
return spec.addMatcherResult.mostRecentCall.args[0];
|
||||
}
|
||||
|
||||
function catchException(fn) {
|
||||
try {
|
||||
fn.call();
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
throw new Error("expected function to throw an exception");
|
||||
}
|
||||
|
||||
it("toEqual with primitives, objects, dates, etc.", function() {
|
||||
expect(match(true).toEqual(true)).toPass();
|
||||
|
||||
expect(match({foo:'bar'}).toEqual(null)).toFail();
|
||||
|
||||
var functionA = function() {
|
||||
return 'hi';
|
||||
};
|
||||
var functionB = function() {
|
||||
return 'hi';
|
||||
};
|
||||
expect(match({foo:functionA}).toEqual({foo:functionB})).toFail();
|
||||
expect(match({foo:functionA}).toEqual({foo:functionA})).toPass();
|
||||
|
||||
expect((match(false).toEqual(true))).toFail();
|
||||
|
||||
var circularGraph = {};
|
||||
circularGraph.referenceToSelf = circularGraph;
|
||||
expect((match(circularGraph).toEqual(circularGraph))).toPass();
|
||||
|
||||
expect((match(new Date(2008, 1, 3, 15, 17, 19, 1234)).toEqual(new Date(2009, 1, 3, 15, 17, 19, 1234)))).toFail();
|
||||
expect((match(new Date(2008, 1, 3, 15, 17, 19, 1234)).toEqual(new Date(2008, 1, 3, 15, 17, 19, 1234)))).toPass();
|
||||
|
||||
|
||||
expect(match(true).toNotEqual(false)).toPass();
|
||||
expect((match(true).toNotEqual(true))).toFail();
|
||||
|
||||
expect((match(['a', 'b']).toEqual(['a', jasmine.undefined]))).toFail();
|
||||
expect((match(['a', 'b']).toEqual(['a', 'b', jasmine.undefined]))).toFail();
|
||||
|
||||
expect((match(new String("cat")).toEqual("cat"))).toPass();
|
||||
expect((match(new String("cat")).toNotEqual("cat"))).toFail();
|
||||
|
||||
expect((match(new Number(5)).toEqual(5))).toPass();
|
||||
expect((match(new Number('5')).toEqual(5))).toPass();
|
||||
expect((match(new Number(5)).toNotEqual(5))).toFail();
|
||||
expect((match(new Number('5')).toNotEqual(5))).toFail();
|
||||
});
|
||||
|
||||
it("toEqual with DOM nodes", function() {
|
||||
var nodeA = document.createElement('div');
|
||||
var nodeB = document.createElement('div');
|
||||
expect((match(nodeA).toEqual(nodeA))).toPass();
|
||||
expect((match(nodeA).toEqual(nodeB))).toFail();
|
||||
});
|
||||
|
||||
it("toEqual to build an Expectation Result", function() {
|
||||
var actual = 'a';
|
||||
var matcher = match(actual);
|
||||
var expected = 'b';
|
||||
matcher.toEqual(expected);
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toEqual");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toMatch(jasmine.pp(actual));
|
||||
expect(result.message).toMatch(jasmine.pp(expected));
|
||||
expect(result.expected).toEqual(expected);
|
||||
expect(result.actual).toEqual(actual);
|
||||
});
|
||||
|
||||
it("toNotEqual to build an Expectation Result", function() {
|
||||
var str = 'a';
|
||||
var matcher = match(str);
|
||||
matcher.toNotEqual(str);
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toNotEqual");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toMatch(jasmine.pp(str));
|
||||
expect(result.message).toMatch('not');
|
||||
expect(result.expected).toEqual(str);
|
||||
expect(result.actual).toEqual(str);
|
||||
});
|
||||
|
||||
it('toBe should return true only if the expected and actual items === each other', function() {
|
||||
var a = {};
|
||||
var b = {};
|
||||
//noinspection UnnecessaryLocalVariableJS
|
||||
var c = a;
|
||||
expect((match(a).toBe(b))).toFail();
|
||||
expect((match(a).toBe(a))).toPass();
|
||||
expect((match(a).toBe(c))).toPass();
|
||||
expect((match(a).toNotBe(b))).toPass();
|
||||
expect((match(a).toNotBe(a))).toFail();
|
||||
expect((match(a).toNotBe(c))).toFail();
|
||||
});
|
||||
|
||||
it("toBe to build an ExpectationResult", function() {
|
||||
var expected = 'b';
|
||||
var actual = 'a';
|
||||
var matcher = match(actual);
|
||||
matcher.toBe(expected);
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toBe");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toMatch(jasmine.pp(actual));
|
||||
expect(result.message).toMatch(jasmine.pp(expected));
|
||||
expect(result.expected).toEqual(expected);
|
||||
expect(result.actual).toEqual(actual);
|
||||
});
|
||||
|
||||
it("toNotBe to build an ExpectationResult", function() {
|
||||
var str = 'a';
|
||||
var matcher = match(str);
|
||||
matcher.toNotBe(str);
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toNotBe");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toMatch(str);
|
||||
expect(result.expected).toEqual(str);
|
||||
expect(result.actual).toEqual(str);
|
||||
});
|
||||
|
||||
it("toMatch and #toNotMatch should perform regular expression matching on strings", function() {
|
||||
expect((match('foobarbel').toMatch(/bar/))).toPass();
|
||||
expect((match('foobazbel').toMatch(/bar/))).toFail();
|
||||
|
||||
expect((match('foobarbel').toMatch("bar"))).toPass();
|
||||
expect((match('foobazbel').toMatch("bar"))).toFail();
|
||||
|
||||
expect((match('foobarbel').toNotMatch(/bar/))).toFail();
|
||||
expect((match('foobazbel').toNotMatch(/bar/))).toPass();
|
||||
|
||||
expect((match('foobarbel').toNotMatch("bar"))).toFail();
|
||||
expect((match('foobazbel').toNotMatch("bar"))).toPass();
|
||||
});
|
||||
|
||||
it("toMatch w/ RegExp to build an ExpectationResult", function() {
|
||||
var actual = 'a';
|
||||
var matcher = match(actual);
|
||||
var expected = /b/;
|
||||
matcher.toMatch(expected);
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toMatch");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toMatch(jasmine.pp(actual));
|
||||
expect(result.message).toMatch(expected.toString());
|
||||
expect(result.expected).toEqual(expected);
|
||||
expect(result.actual).toEqual(actual);
|
||||
});
|
||||
|
||||
it("toMatch w/ String to build an ExpectationResult", function() {
|
||||
var actual = 'a';
|
||||
var matcher = match(actual);
|
||||
var expected = 'b';
|
||||
matcher.toMatch(expected);
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toMatch");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toEqual("Expected 'a' to match 'b'.");
|
||||
expect(result.expected).toEqual(expected);
|
||||
expect(result.actual).toEqual(actual);
|
||||
});
|
||||
|
||||
it("toNotMatch w/ RegExp to build an ExpectationResult", function() {
|
||||
var actual = 'a';
|
||||
var matcher = match(actual);
|
||||
var expected = /a/;
|
||||
matcher.toNotMatch(expected);
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toNotMatch");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toEqual("Expected 'a' to not match /a/.");
|
||||
expect(result.expected).toEqual(expected);
|
||||
expect(result.actual).toEqual(actual);
|
||||
});
|
||||
|
||||
it("toNotMatch w/ String to build an ExpectationResult", function() {
|
||||
var str = 'a';
|
||||
var matcher = match(str);
|
||||
matcher.toNotMatch(str);
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toNotMatch");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toEqual("Expected 'a' to not match 'a'.");
|
||||
expect(result.expected).toEqual(str);
|
||||
expect(result.actual).toEqual(str);
|
||||
});
|
||||
|
||||
it("toBeDefined", function() {
|
||||
expect(match('foo').toBeDefined()).toPass();
|
||||
expect(match(jasmine.undefined).toBeDefined()).toFail();
|
||||
});
|
||||
|
||||
it("toBeDefined to build an ExpectationResult", function() {
|
||||
var matcher = match(jasmine.undefined);
|
||||
matcher.toBeDefined();
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toBeDefined");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toEqual('Expected undefined to be defined.');
|
||||
expect(result.actual).toEqual(jasmine.undefined);
|
||||
});
|
||||
|
||||
it("toBeUndefined", function() {
|
||||
expect(match('foo').toBeUndefined()).toFail();
|
||||
expect(match(jasmine.undefined).toBeUndefined()).toPass();
|
||||
});
|
||||
|
||||
it("toBeNull", function() {
|
||||
expect(match(null).toBeNull()).toPass();
|
||||
expect(match(jasmine.undefined).toBeNull()).toFail();
|
||||
expect(match("foo").toBeNull()).toFail();
|
||||
});
|
||||
|
||||
it("toBeNull w/ String to build an ExpectationResult", function() {
|
||||
var actual = 'a';
|
||||
var matcher = match(actual);
|
||||
matcher.toBeNull();
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toBeNull");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toMatch(jasmine.pp(actual));
|
||||
expect(result.message).toMatch('null');
|
||||
expect(result.actual).toEqual(actual);
|
||||
});
|
||||
|
||||
it("toBeNull w/ Object to build an ExpectationResult", function() {
|
||||
var actual = {a: 'b'};
|
||||
var matcher = match(actual);
|
||||
matcher.toBeNull();
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toBeNull");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toMatch(jasmine.pp(actual));
|
||||
expect(result.message).toMatch('null');
|
||||
expect(result.actual).toEqual(actual);
|
||||
});
|
||||
|
||||
it("toBeFalsy", function() {
|
||||
expect(match(false).toBeFalsy()).toPass();
|
||||
expect(match(true).toBeFalsy()).toFail();
|
||||
expect(match(jasmine.undefined).toBeFalsy()).toPass();
|
||||
expect(match(0).toBeFalsy()).toPass();
|
||||
expect(match("").toBeFalsy()).toPass();
|
||||
});
|
||||
|
||||
it("toBeFalsy to build an ExpectationResult", function() {
|
||||
var actual = 'a';
|
||||
var matcher = match(actual);
|
||||
matcher.toBeFalsy();
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toBeFalsy");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toMatch(jasmine.pp(actual));
|
||||
expect(result.message).toMatch('falsy');
|
||||
expect(result.actual).toEqual(actual);
|
||||
});
|
||||
|
||||
it("toBeTruthy", function() {
|
||||
expect(match(false).toBeTruthy()).toFail();
|
||||
expect(match(true).toBeTruthy()).toPass();
|
||||
expect(match(jasmine.undefined).toBeTruthy()).toFail();
|
||||
expect(match(0).toBeTruthy()).toFail();
|
||||
expect(match("").toBeTruthy()).toFail();
|
||||
expect(match("hi").toBeTruthy()).toPass();
|
||||
expect(match(5).toBeTruthy()).toPass();
|
||||
expect(match({foo: 1}).toBeTruthy()).toPass();
|
||||
});
|
||||
|
||||
it("toBeTruthy to build an ExpectationResult", function() {
|
||||
var matcher = match(false);
|
||||
matcher.toBeTruthy();
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toBeTruthy");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toEqual("Expected false to be truthy.");
|
||||
expect(result.actual).toFail();
|
||||
});
|
||||
|
||||
it("toEqual", function() {
|
||||
expect(match(jasmine.undefined).toEqual(jasmine.undefined)).toPass();
|
||||
expect(match({foo:'bar'}).toEqual({foo:'bar'})).toPass();
|
||||
expect(match("foo").toEqual({bar: jasmine.undefined})).toFail();
|
||||
expect(match({foo: jasmine.undefined}).toEqual("goo")).toFail();
|
||||
expect(match({foo: {bar :jasmine.undefined}}).toEqual("goo")).toFail();
|
||||
});
|
||||
|
||||
it("toEqual with jasmine.any()", function() {
|
||||
expect(match("foo").toEqual(jasmine.any(String))).toPass();
|
||||
expect(match(3).toEqual(jasmine.any(Number))).toPass();
|
||||
expect(match("foo").toEqual(jasmine.any(Function))).toFail();
|
||||
expect(match("foo").toEqual(jasmine.any(Object))).toFail();
|
||||
expect(match({someObj:'foo'}).toEqual(jasmine.any(Object))).toPass();
|
||||
expect(match({someObj:'foo'}).toEqual(jasmine.any(Function))).toFail();
|
||||
expect(match(function() {
|
||||
}).toEqual(jasmine.any(Object))).toFail();
|
||||
expect(match(["foo", "goo"]).toEqual(["foo", jasmine.any(String)])).toPass();
|
||||
expect(match(function() {
|
||||
}).toEqual(jasmine.any(Function))).toPass();
|
||||
expect(match(["a", function() {
|
||||
}]).toEqual(["a", jasmine.any(Function)])).toPass();
|
||||
});
|
||||
|
||||
it("toEqual handles circular objects ok", function() {
|
||||
expect(match({foo: "bar", baz: jasmine.undefined}).toEqual({foo: "bar", baz: jasmine.undefined})).toPass();
|
||||
expect(match({foo:['bar','baz','quux']}).toEqual({foo:['bar','baz','quux']})).toPass();
|
||||
expect(match({foo: {bar:'baz'}, quux:'corge'}).toEqual({foo:{bar:'baz'}, quux:'corge'})).toPass();
|
||||
|
||||
var circularObject = {};
|
||||
var secondCircularObject = {};
|
||||
circularObject.field = circularObject;
|
||||
secondCircularObject.field = secondCircularObject;
|
||||
expect(match(circularObject).toEqual(secondCircularObject)).toPass();
|
||||
});
|
||||
|
||||
it("toNotEqual as slightly surprising behavior, but is it intentional?", function() {
|
||||
expect(match({x:"x", y:"y", z:"w"}).toNotEqual({x:"x", y:"y", z:"z"})).toPass();
|
||||
expect(match({x:"x", y:"y", w:"z"}).toNotEqual({x:"x", y:"y", z:"z"})).toPass();
|
||||
expect(match({x:"x", y:"y", z:"z"}).toNotEqual({w: "w", x:"x", y:"y", z:"z"})).toPass();
|
||||
expect(match({w: "w", x:"x", y:"y", z:"z"}).toNotEqual({x:"x", y:"y", z:"z"})).toPass();
|
||||
});
|
||||
|
||||
it("toEqual handles arrays", function() {
|
||||
expect(match([1, "A"]).toEqual([1, "A"])).toPass();
|
||||
});
|
||||
|
||||
it("toContain and toNotContain", function() {
|
||||
expect(match('ABC').toContain('A')).toPass();
|
||||
expect(match('ABC').toContain('X')).toFail();
|
||||
|
||||
expect(match(['A', 'B', 'C']).toContain('A')).toPass();
|
||||
expect(match(['A', 'B', 'C']).toContain('F')).toFail();
|
||||
expect(match(['A', 'B', 'C']).toNotContain('F')).toPass();
|
||||
expect(match(['A', 'B', 'C']).toNotContain('A')).toFail();
|
||||
|
||||
expect(match(['A', {some:'object'}, 'C']).toContain({some:'object'})).toPass();
|
||||
expect(match(['A', {some:'object'}, 'C']).toContain({some:'other object'})).toFail();
|
||||
});
|
||||
|
||||
it("toContain to build an ExpectationResult", function() {
|
||||
var actual = ['a','b','c'];
|
||||
var matcher = match(actual);
|
||||
var expected = 'x';
|
||||
matcher.toContain(expected);
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toContain");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toMatch(jasmine.pp(actual));
|
||||
expect(result.message).toMatch('contain');
|
||||
expect(result.message).toMatch(jasmine.pp(expected));
|
||||
expect(result.actual).toEqual(actual);
|
||||
expect(result.expected).toEqual(expected);
|
||||
});
|
||||
|
||||
it("toNotContain to build an ExpectationResult", function() {
|
||||
var actual = ['a','b','c'];
|
||||
var matcher = match(actual);
|
||||
var expected = 'b';
|
||||
matcher.toNotContain(expected);
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toNotContain");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toMatch(jasmine.pp(actual));
|
||||
expect(result.message).toMatch('not contain');
|
||||
expect(result.message).toMatch(jasmine.pp(expected));
|
||||
expect(result.actual).toEqual(actual);
|
||||
expect(result.expected).toEqual(expected);
|
||||
});
|
||||
|
||||
it("toBeLessThan should pass if actual is less than expected", function() {
|
||||
expect(match(37).toBeLessThan(42)).toPass();
|
||||
expect(match(37).toBeLessThan(-42)).toFail();
|
||||
expect(match(37).toBeLessThan(37)).toFail();
|
||||
});
|
||||
|
||||
it("toBeLessThan to build an ExpectationResult", function() {
|
||||
var actual = 3;
|
||||
var matcher = match(actual);
|
||||
var expected = 1;
|
||||
matcher.toBeLessThan(expected);
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toBeLessThan");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toMatch(jasmine.pp(actual) + ' to be less than');
|
||||
expect(result.message).toMatch(jasmine.pp(expected));
|
||||
expect(result.actual).toEqual(actual);
|
||||
expect(result.expected).toEqual(expected);
|
||||
});
|
||||
|
||||
it("toBeGreaterThan should pass if actual is greater than expected", function() {
|
||||
expect(match(37).toBeGreaterThan(42)).toFail();
|
||||
expect(match(37).toBeGreaterThan(-42)).toPass();
|
||||
expect(match(37).toBeGreaterThan(37)).toFail();
|
||||
});
|
||||
|
||||
it("toBeGreaterThan to build an ExpectationResult", function() {
|
||||
var actual = 1;
|
||||
var matcher = match(actual);
|
||||
var expected = 3;
|
||||
matcher.toBeGreaterThan(expected);
|
||||
|
||||
var result = lastResult();
|
||||
|
||||
expect(result.matcherName).toEqual("toBeGreaterThan");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toMatch(jasmine.pp(actual) + ' to be greater than');
|
||||
expect(result.message).toMatch(jasmine.pp(expected));
|
||||
expect(result.actual).toEqual(actual);
|
||||
expect(result.expected).toEqual(expected);
|
||||
});
|
||||
|
||||
describe("toThrow", function() {
|
||||
describe("when code block throws an exception", function() {
|
||||
var throwingFn;
|
||||
|
||||
beforeEach(function() {
|
||||
throwingFn = function() {
|
||||
throw new Error("Fake Error");
|
||||
};
|
||||
});
|
||||
|
||||
it("should match any exception", function() {
|
||||
expect(match(throwingFn).toThrow()).toPass();
|
||||
});
|
||||
|
||||
it("should match exceptions specified by message", function() {
|
||||
expect(match(throwingFn).toThrow("Fake Error")).toPass();
|
||||
expect(match(throwingFn).toThrow("Other Error")).toFail();
|
||||
expect(lastResult().message).toMatch("Other Error");
|
||||
});
|
||||
|
||||
it("should match exceptions specified by Error", function() {
|
||||
expect(match(throwingFn).toThrow(new Error("Fake Error"))).toPass();
|
||||
expect(match(throwingFn).toThrow(new Error("Other Error"))).toFail();
|
||||
expect(lastResult().message).toMatch("Other Error");
|
||||
});
|
||||
|
||||
describe("and matcher is inverted with .not", function() {
|
||||
it("should match any exception", function() {
|
||||
expect(match(throwingFn).not.toThrow()).toFail();
|
||||
expect(lastResult().message).toMatch(/Expected function not to throw an exception/);
|
||||
});
|
||||
|
||||
it("should match exceptions specified by message", function() {
|
||||
expect(match(throwingFn).not.toThrow("Fake Error")).toFail();
|
||||
// expect(lastResult().message).toMatch(/Expected function not to throw Fake Error./);
|
||||
expect(match(throwingFn).not.toThrow("Other Error")).toPass();
|
||||
});
|
||||
|
||||
it("should match exceptions specified by Error", function() {
|
||||
expect(match(throwingFn).not.toThrow(new Error("Fake Error"))).toFail();
|
||||
// expect(lastResult().message).toMatch("Other Error");
|
||||
expect(match(throwingFn).not.toThrow(new Error("Other Error"))).toPass();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when actual is not a function", function() {
|
||||
it("should fail with an exception", function() {
|
||||
var exception = catchException(function() {
|
||||
match('not-a-function').toThrow();
|
||||
});
|
||||
expect(exception).toBeDefined();
|
||||
expect(exception.message).toEqual('Actual is not a function');
|
||||
});
|
||||
|
||||
describe("and matcher is inverted with .not", function() {
|
||||
it("should fail with an exception", function() {
|
||||
var exception = catchException(function() {
|
||||
match('not-a-function').not.toThrow();
|
||||
});
|
||||
expect(exception).toBeDefined();
|
||||
expect(exception.message).toEqual('Actual is not a function');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("when code block does not throw an exception", function() {
|
||||
it("should fail (or pass when inverted with .not)", function() {
|
||||
expect(match(function() {
|
||||
}).toThrow()).toFail();
|
||||
expect(lastResult().message).toEqual('Expected function to throw an exception.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(".not.matcher", function() {
|
||||
it("should invert the sense of any matcher", function() {
|
||||
expect(match(37).not.toBeGreaterThan(42)).toPass();
|
||||
expect(match(42).not.toBeGreaterThan(37)).toFail();
|
||||
expect(match("abc").not.toEqual("def")).toPass();
|
||||
expect(match("abc").not.toEqual("abc")).toFail();
|
||||
});
|
||||
|
||||
it("should provide an inverted default message", function() {
|
||||
match(37).not.toBeGreaterThan(42);
|
||||
expect(lastResult().message).toEqual("Passed.");
|
||||
|
||||
match(42).not.toBeGreaterThan(37);
|
||||
expect(lastResult().message).toEqual("Expected 42 not to be greater than 37.");
|
||||
});
|
||||
|
||||
it("should use the second message when the matcher sets an array of custom messages", function() {
|
||||
spec.addMatchers({
|
||||
custom: function() {
|
||||
this.message = function() {
|
||||
return ['Expected it was called.', 'Expected it wasn\'t called.'];
|
||||
};
|
||||
return this.actual;
|
||||
}
|
||||
});
|
||||
|
||||
match(true).custom();
|
||||
expect(lastResult().message).toEqual("Passed.");
|
||||
match(false).custom();
|
||||
expect(lastResult().message).toEqual("Expected it was called.");
|
||||
match(true).not.custom();
|
||||
expect(lastResult().message).toEqual("Expected it wasn't called.");
|
||||
match(false).not.custom();
|
||||
expect(lastResult().message).toEqual("Passed.");
|
||||
});
|
||||
});
|
||||
|
||||
describe("spy matchers >>", function() {
|
||||
var TestClass;
|
||||
beforeEach(function() {
|
||||
TestClass = {
|
||||
normalFunction: function() {
|
||||
},
|
||||
spyFunction: jasmine.createSpy("My spy")
|
||||
};
|
||||
});
|
||||
|
||||
function shouldThrowAnExceptionWhenInvokedOnANonSpy(methodName) {
|
||||
return function() {
|
||||
expect(function() {
|
||||
match(TestClass.normalFunction)[methodName]();
|
||||
}).toThrow('Expected a spy, but got Function.');
|
||||
|
||||
expect(function() {
|
||||
match(jasmine.undefined)[methodName]();
|
||||
}).toThrow('Expected a spy, but got undefined.');
|
||||
|
||||
expect(function() {
|
||||
match({some:'object'})[methodName]();
|
||||
}).toThrow('Expected a spy, but got { some : \'object\' }.');
|
||||
|
||||
expect(function() {
|
||||
match("<b>")[methodName]();
|
||||
}).toThrow('Expected a spy, but got \'<b>\'.');
|
||||
};
|
||||
}
|
||||
|
||||
describe("toHaveBeenCalled", function() {
|
||||
it("should pass if the spy was called", function() {
|
||||
expect(match(TestClass.spyFunction).toHaveBeenCalled()).toFail();
|
||||
|
||||
TestClass.spyFunction();
|
||||
expect(match(TestClass.spyFunction).toHaveBeenCalled()).toPass();
|
||||
});
|
||||
|
||||
it("should throw an exception when invoked with any arguments", function() {
|
||||
expect(function() {
|
||||
match(TestClass.normalFunction).toHaveBeenCalled("unwanted argument");
|
||||
}).toThrow('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
|
||||
});
|
||||
|
||||
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('toHaveBeenCalled'));
|
||||
});
|
||||
|
||||
describe("wasCalled", function() {
|
||||
it("should alias toHaveBeenCalled", function() {
|
||||
spyOn(TestClass, 'normalFunction');
|
||||
|
||||
TestClass.normalFunction();
|
||||
|
||||
expect(TestClass.normalFunction).wasCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("wasNotCalled", function() {
|
||||
it("should pass iff the spy was not called", function() {
|
||||
expect(match(TestClass.spyFunction).wasNotCalled()).toPass();
|
||||
|
||||
TestClass.spyFunction();
|
||||
expect(match(TestClass.spyFunction).wasNotCalled()).toFail();
|
||||
});
|
||||
|
||||
it("should throw an exception when invoked with any arguments", function() {
|
||||
expect(function() {
|
||||
match(TestClass.normalFunction).wasNotCalled("unwanted argument");
|
||||
}).toThrow('wasNotCalled does not take arguments');
|
||||
});
|
||||
|
||||
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('wasNotCalled'));
|
||||
});
|
||||
|
||||
describe("toHaveBeenCalledWith", function() {
|
||||
it('toHaveBeenCalledWith should return true if it was called with the expected args', function() {
|
||||
TestClass.spyFunction('a', 'b', 'c');
|
||||
expect(match(TestClass.spyFunction).toHaveBeenCalledWith('a', 'b', 'c')).toPass();
|
||||
});
|
||||
|
||||
it('should return false if it was not called with the expected args', function() {
|
||||
TestClass.spyFunction('a', 'b', 'c');
|
||||
var expected = match(TestClass.spyFunction);
|
||||
expect(expected.toHaveBeenCalledWith('c', 'b', 'a')).toFail();
|
||||
var result = lastResult();
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.expected).toEqual(['c', 'b', 'a']);
|
||||
expect(result.actual.mostRecentCall.args).toEqual(['a', 'b', 'c']);
|
||||
expect(result.message).toContain(jasmine.pp(result.expected));
|
||||
expect(result.message).toContain(jasmine.pp(result.actual.mostRecentCall.args));
|
||||
});
|
||||
|
||||
it('should return false if it was not called', function() {
|
||||
var expected = match(TestClass.spyFunction);
|
||||
expect(expected.toHaveBeenCalledWith('c', 'b', 'a')).toFail();
|
||||
var result = lastResult();
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.expected).toEqual(['c', 'b', 'a']);
|
||||
expect(result.actual.argsForCall).toEqual([]);
|
||||
expect(result.message).toContain(jasmine.pp(result.expected));
|
||||
});
|
||||
|
||||
it('should allow matches across multiple calls', function() {
|
||||
TestClass.spyFunction('a', 'b', 'c');
|
||||
TestClass.spyFunction('d', 'e', 'f');
|
||||
var expected = match(TestClass.spyFunction);
|
||||
expect(expected.toHaveBeenCalledWith('a', 'b', 'c')).toPass();
|
||||
expect(expected.toHaveBeenCalledWith('d', 'e', 'f')).toPass();
|
||||
expect(expected.toHaveBeenCalledWith('x', 'y', 'z')).toFail();
|
||||
});
|
||||
|
||||
it("should return a decent message", function() {
|
||||
TestClass.spyFunction('a', 'b', 'c');
|
||||
TestClass.spyFunction('d', 'e', 'f');
|
||||
var expected = match(TestClass.spyFunction);
|
||||
expect(expected.toHaveBeenCalledWith('a', 'b')).toFail();
|
||||
expect(lastResult().message).toEqual("Expected spy to have been called with [ 'a', 'b' ] but was called with [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] ]");
|
||||
});
|
||||
|
||||
it("should return a decent message when inverted", function() {
|
||||
TestClass.spyFunction('a', 'b', 'c');
|
||||
TestClass.spyFunction('d', 'e', 'f');
|
||||
var expected = match(TestClass.spyFunction);
|
||||
expect(expected.not.toHaveBeenCalledWith('a', 'b', 'c')).toFail();
|
||||
expect(lastResult().message).toEqual("Expected spy not to have been called with [ 'a', 'b', 'c' ] but was called with [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] ]");
|
||||
});
|
||||
|
||||
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('toHaveBeenCalledWith'));
|
||||
|
||||
describe("to build an ExpectationResult", function () {
|
||||
beforeEach(function() {
|
||||
var currentSuite;
|
||||
var spec;
|
||||
currentSuite = env.describe('default current suite', function() {
|
||||
spec = env.it();
|
||||
}, spec);
|
||||
TestClass = { someFunction: function(a, b) {
|
||||
} };
|
||||
spec.spyOn(TestClass, 'someFunction');
|
||||
});
|
||||
|
||||
it("should should handle the case of a spy", function() {
|
||||
TestClass.someFunction('a', 'c');
|
||||
var matcher = match(TestClass.someFunction);
|
||||
matcher.toHaveBeenCalledWith('a', 'b');
|
||||
|
||||
var result = lastResult();
|
||||
expect(result.matcherName).toEqual("toHaveBeenCalledWith");
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.message).toContain(jasmine.pp(['a', 'b']));
|
||||
expect(result.message).toContain(jasmine.pp(['a', 'c']));
|
||||
expect(result.actual).toEqual(TestClass.someFunction);
|
||||
expect(result.expected).toEqual(['a','b']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("wasCalledWith", function() {
|
||||
it("should alias toHaveBeenCalledWith", function() {
|
||||
spyOn(TestClass, 'normalFunction');
|
||||
|
||||
TestClass.normalFunction(123);
|
||||
|
||||
expect(TestClass.normalFunction).wasCalledWith(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe("wasNotCalledWith", function() {
|
||||
it('should return true if the spy was NOT called with the expected args', function() {
|
||||
TestClass.spyFunction('a', 'b', 'c');
|
||||
expect(match(TestClass.spyFunction).wasNotCalledWith('c', 'b', 'a')).toPass();
|
||||
});
|
||||
|
||||
it('should return false if it WAS called with the expected args', function() {
|
||||
TestClass.spyFunction('a', 'b', 'c');
|
||||
var expected = match(TestClass.spyFunction);
|
||||
expect(expected.wasNotCalledWith('a', 'b', 'c')).toFail();
|
||||
var result = lastResult();
|
||||
expect(result.passed()).toFail();
|
||||
expect(result.expected).toEqual(['a', 'b', 'c']);
|
||||
expect(result.actual.mostRecentCall.args).toEqual(['a', 'b', 'c']);
|
||||
expect(result.message).toContain(jasmine.pp(result.expected));
|
||||
});
|
||||
|
||||
it('should return true if it was not called', function() {
|
||||
var expected = match(TestClass.spyFunction);
|
||||
expect(expected.wasNotCalledWith('c', 'b', 'a')).toPass();
|
||||
});
|
||||
|
||||
it('should allow matches across multiple calls', function() {
|
||||
var expected = match(TestClass.spyFunction);
|
||||
TestClass.spyFunction('a', 'b', 'c');
|
||||
TestClass.spyFunction('d', 'e', 'f');
|
||||
expect(expected.wasNotCalledWith('a', 'b', 'c')).toFail();
|
||||
expect(expected.wasNotCalledWith('d', 'e', 'f')).toFail();
|
||||
expect(expected.wasNotCalledWith('x', 'y', 'z')).toPass();
|
||||
});
|
||||
|
||||
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('wasNotCalledWith'));
|
||||
});
|
||||
});
|
||||
|
||||
describe("all matchers", function() {
|
||||
it("should return null, for future-proofing, since we might eventually allow matcher chaining", function() {
|
||||
expect(match(true).toBe(true)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
describe("MockClock", function () {
|
||||
|
||||
beforeEach(function() {
|
||||
jasmine.Clock.useMock();
|
||||
});
|
||||
|
||||
describe("setTimeout", function () {
|
||||
it("should mock the clock when useMock is in a beforeEach", function() {
|
||||
var expected = false;
|
||||
setTimeout(function() {
|
||||
expected = true;
|
||||
}, 30000);
|
||||
expect(expected).toBe(false);
|
||||
jasmine.Clock.tick(30001);
|
||||
expect(expected).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("setInterval", function () {
|
||||
it("should mock the clock when useMock is in a beforeEach", function() {
|
||||
var interval = 0;
|
||||
setInterval(function() {
|
||||
interval++;
|
||||
}, 30000);
|
||||
expect(interval).toEqual(0);
|
||||
jasmine.Clock.tick(30001);
|
||||
expect(interval).toEqual(1);
|
||||
jasmine.Clock.tick(30001);
|
||||
expect(interval).toEqual(2);
|
||||
jasmine.Clock.tick(1);
|
||||
expect(interval).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
it("shouldn't complain if you call jasmine.Clock.useMock() more than once", function() {
|
||||
jasmine.Clock.useMock();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
describe("jasmine.MultiReporter", function() {
|
||||
var multiReporter, fakeReporter1, fakeReporter2;
|
||||
|
||||
beforeEach(function() {
|
||||
multiReporter = new jasmine.MultiReporter();
|
||||
fakeReporter1 = jasmine.createSpyObj("fakeReporter1", ["reportSpecResults"]);
|
||||
fakeReporter2 = jasmine.createSpyObj("fakeReporter2", ["reportSpecResults", "reportRunnerStarting"]);
|
||||
multiReporter.addReporter(fakeReporter1);
|
||||
multiReporter.addReporter(fakeReporter2);
|
||||
});
|
||||
|
||||
it("should support all the method calls that jasmine.Reporter supports", function() {
|
||||
var delegate = {};
|
||||
multiReporter.addReporter(delegate);
|
||||
|
||||
this.addMatchers({
|
||||
toDelegateMethod: function(methodName) {
|
||||
delegate[methodName] = jasmine.createSpy(methodName);
|
||||
this.actual[methodName]("whatever argument");
|
||||
|
||||
return delegate[methodName].wasCalled
|
||||
&& delegate[methodName].mostRecentCall.args.length == 1
|
||||
&& delegate[methodName].mostRecentCall.args[0] == "whatever argument";
|
||||
}
|
||||
});
|
||||
|
||||
expect(multiReporter).toDelegateMethod('reportRunnerStarting');
|
||||
expect(multiReporter).toDelegateMethod('reportRunnerResults');
|
||||
expect(multiReporter).toDelegateMethod('reportSuiteResults');
|
||||
expect(multiReporter).toDelegateMethod('reportSpecStarting');
|
||||
expect(multiReporter).toDelegateMethod('reportSpecResults');
|
||||
expect(multiReporter).toDelegateMethod('log');
|
||||
});
|
||||
|
||||
it("should delegate to any and all subreporters", function() {
|
||||
multiReporter.reportSpecResults('blah', 'foo');
|
||||
expect(fakeReporter1.reportSpecResults).toHaveBeenCalledWith('blah', 'foo');
|
||||
expect(fakeReporter2.reportSpecResults).toHaveBeenCalledWith('blah', 'foo');
|
||||
});
|
||||
|
||||
it("should quietly skip delegating to any subreporters which lack the given method", function() {
|
||||
multiReporter.reportRunnerStarting('blah', 'foo');
|
||||
expect(fakeReporter2.reportRunnerStarting).toHaveBeenCalledWith('blah', 'foo');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
describe('jasmine.NestedResults', function() {
|
||||
it('#addResult increments counters', function() {
|
||||
// Leaf case
|
||||
var results = new jasmine.NestedResults();
|
||||
|
||||
results.addResult(new jasmine.ExpectationResult({
|
||||
matcherName: "foo", passed: true, message: 'Passed.', actual: 'bar', expected: 'bar'}
|
||||
));
|
||||
|
||||
expect(results.getItems().length).toEqual(1);
|
||||
expect(results.totalCount).toEqual(1);
|
||||
expect(results.passedCount).toEqual(1);
|
||||
expect(results.failedCount).toEqual(0);
|
||||
|
||||
results.addResult(new jasmine.ExpectationResult({
|
||||
matcherName: "baz", passed: false, message: 'FAIL.', actual: "corge", expected: "quux"
|
||||
}));
|
||||
|
||||
expect(results.getItems().length).toEqual(2);
|
||||
expect(results.totalCount).toEqual(2);
|
||||
expect(results.passedCount).toEqual(1);
|
||||
expect(results.failedCount).toEqual(1);
|
||||
});
|
||||
|
||||
it('should roll up counts for nested results', function() {
|
||||
// Branch case
|
||||
var leafResultsOne = new jasmine.NestedResults();
|
||||
leafResultsOne.addResult(new jasmine.ExpectationResult({
|
||||
matcherName: "toSomething", passed: true, message: 'message', actual: '', expected:''
|
||||
}));
|
||||
|
||||
leafResultsOne.addResult(new jasmine.ExpectationResult({
|
||||
matcherName: "toSomethingElse", passed: false, message: 'message', actual: 'a', expected: 'b'
|
||||
}));
|
||||
|
||||
var leafResultsTwo = new jasmine.NestedResults();
|
||||
leafResultsTwo.addResult(new jasmine.ExpectationResult({
|
||||
matcherName: "toSomething", passed: true, message: 'message', actual: '', expected: ''
|
||||
}));
|
||||
leafResultsTwo.addResult(new jasmine.ExpectationResult({
|
||||
matcherName: "toSomethineElse", passed: false, message: 'message', actual: 'c', expected: 'd'
|
||||
}));
|
||||
|
||||
var branchResults = new jasmine.NestedResults();
|
||||
branchResults.addResult(leafResultsOne);
|
||||
branchResults.addResult(leafResultsTwo);
|
||||
|
||||
expect(branchResults.getItems().length).toEqual(2);
|
||||
expect(branchResults.totalCount).toEqual(4);
|
||||
expect(branchResults.passedCount).toEqual(2);
|
||||
expect(branchResults.failedCount).toEqual(2);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
describe("jasmine.pp", function () {
|
||||
it("should wrap strings in single quotes", function() {
|
||||
expect(jasmine.pp("some string")).toEqual("'some string'");
|
||||
expect(jasmine.pp("som' string")).toEqual("'som' string'");
|
||||
});
|
||||
|
||||
it("should stringify primitives properly", function() {
|
||||
expect(jasmine.pp(true)).toEqual("true");
|
||||
expect(jasmine.pp(false)).toEqual("false");
|
||||
expect(jasmine.pp(null)).toEqual("null");
|
||||
expect(jasmine.pp(jasmine.undefined)).toEqual("undefined");
|
||||
expect(jasmine.pp(3)).toEqual("3");
|
||||
expect(jasmine.pp(-3.14)).toEqual("-3.14");
|
||||
});
|
||||
|
||||
it("should stringify arrays properly", function() {
|
||||
expect(jasmine.pp([1, 2])).toEqual("[ 1, 2 ]");
|
||||
expect(jasmine.pp([1, 'foo', {}, jasmine.undefined, null])).toEqual("[ 1, 'foo', { }, undefined, null ]");
|
||||
});
|
||||
|
||||
it("should indicate circular array references", function() {
|
||||
var array1 = [1, 2];
|
||||
var array2 = [array1];
|
||||
array1.push(array2);
|
||||
expect(jasmine.pp(array1)).toEqual("[ 1, 2, [ <circular reference: Array> ] ]");
|
||||
});
|
||||
|
||||
it("should stringify objects properly", function() {
|
||||
expect(jasmine.pp({foo: 'bar'})).toEqual("{ foo : 'bar' }");
|
||||
expect(jasmine.pp({foo:'bar', baz:3, nullValue: null, undefinedValue: jasmine.undefined})).toEqual("{ foo : 'bar', baz : 3, nullValue : null, undefinedValue : undefined }");
|
||||
expect(jasmine.pp({foo: function () {
|
||||
}, bar: [1, 2, 3]})).toEqual("{ foo : Function, bar : [ 1, 2, 3 ] }");
|
||||
});
|
||||
|
||||
it("should stringify RegExp objects properly", function() {
|
||||
expect(jasmine.pp(/x|y|z/)).toEqual("/x|y|z/");
|
||||
});
|
||||
|
||||
it("should indicate circular object references", function() {
|
||||
var sampleValue = {foo: 'hello'};
|
||||
sampleValue.nested = sampleValue;
|
||||
expect(jasmine.pp(sampleValue)).toEqual("{ foo : 'hello', nested : <circular reference: Object> }");
|
||||
});
|
||||
|
||||
it("should indicate getters on objects as such", function() {
|
||||
var sampleValue = {id: 1};
|
||||
if (sampleValue.__defineGetter__) {
|
||||
//not supported in IE!
|
||||
sampleValue.__defineGetter__('calculatedValue', function() {
|
||||
throw new Error("don't call me!");
|
||||
});
|
||||
}
|
||||
if (sampleValue.__defineGetter__) {
|
||||
expect(jasmine.pp(sampleValue)).toEqual("{ id : 1, calculatedValue : <getter> }");
|
||||
}
|
||||
else {
|
||||
expect(jasmine.pp(sampleValue)).toEqual("{ id : 1 }");
|
||||
}
|
||||
});
|
||||
|
||||
it("should stringify HTML nodes properly", function() {
|
||||
var sampleNode = document.createElement('div');
|
||||
sampleNode.innerHTML = 'foo<b>bar</b>';
|
||||
expect(jasmine.pp(sampleNode)).toEqual("HTMLNode");
|
||||
expect(jasmine.pp({foo: sampleNode})).toEqual("{ foo : HTMLNode }");
|
||||
});
|
||||
|
||||
it('should not do HTML escaping of strings', function() {
|
||||
expect(jasmine.pp('some <b>html string</b> &', false)).toEqual('\'some <b>html string</b> &\'');
|
||||
});
|
||||
|
||||
it("should abbreviate the global (usually window) object", function() {
|
||||
expect(jasmine.pp(jasmine.getGlobal())).toEqual("<global>");
|
||||
});
|
||||
|
||||
it("should stringify Date objects properly", function() {
|
||||
var now = new Date();
|
||||
expect(jasmine.pp(now)).toEqual("Date(" + now.toString() + ")");
|
||||
});
|
||||
|
||||
it("should stringify spy objects properly", function() {
|
||||
var TestObject = {
|
||||
someFunction: function() {
|
||||
}
|
||||
};
|
||||
spyOn(TestObject, 'someFunction');
|
||||
expect(jasmine.pp(TestObject.someFunction)).toEqual("spy on someFunction");
|
||||
|
||||
expect(jasmine.pp(jasmine.createSpy("something"))).toEqual("spy on something");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
describe("jasmine.Queue", function() {
|
||||
it("should not call itself recursively, so we don't get stack overflow errors", function() {
|
||||
var queue = new jasmine.Queue(new jasmine.Env());
|
||||
queue.add(new jasmine.Block(null, function() {}));
|
||||
queue.add(new jasmine.Block(null, function() {}));
|
||||
queue.add(new jasmine.Block(null, function() {}));
|
||||
queue.add(new jasmine.Block(null, function() {}));
|
||||
|
||||
var nestCount = 0;
|
||||
var maxNestCount = 0;
|
||||
var nextCallCount = 0;
|
||||
queue.next_ = function() {
|
||||
nestCount++;
|
||||
if (nestCount > maxNestCount) maxNestCount = nestCount;
|
||||
|
||||
jasmine.Queue.prototype.next_.apply(queue, arguments);
|
||||
nestCount--;
|
||||
};
|
||||
|
||||
queue.start();
|
||||
expect(maxNestCount).toEqual(1);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
describe('jasmine.Reporter', function() {
|
||||
var env;
|
||||
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmine.Env();
|
||||
env.updateInterval = 0;
|
||||
});
|
||||
|
||||
it('should get called from the test runner', function() {
|
||||
env.describe('Suite for JSON Reporter with Callbacks', function () {
|
||||
env.it('should be a test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
env.it('should be a failing test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(false).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
env.describe('Suite for JSON Reporter with Callbacks 2', function () {
|
||||
env.it('should be a test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
var foo = 0;
|
||||
var bar = 0;
|
||||
var baz = 0;
|
||||
|
||||
env.addReporter({
|
||||
reportSpecResults: function() {
|
||||
foo++;
|
||||
},
|
||||
reportSuiteResults: function() {
|
||||
bar++;
|
||||
},
|
||||
reportRunnerResults: function() {
|
||||
baz++;
|
||||
}
|
||||
});
|
||||
|
||||
var runner = env.currentRunner();
|
||||
runner.execute();
|
||||
|
||||
expect(foo).toEqual(3); // 'foo was expected to be 3, was ' + foo);
|
||||
expect(bar).toEqual(2); // 'bar was expected to be 2, was ' + bar);
|
||||
expect(baz).toEqual(1); // 'baz was expected to be 1, was ' + baz);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,267 @@
|
||||
describe('RunnerTest', function() {
|
||||
var fakeTimer;
|
||||
var env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmine.Env();
|
||||
env.updateInterval = 0;
|
||||
|
||||
fakeTimer = new jasmine.FakeTimer();
|
||||
env.setTimeout = fakeTimer.setTimeout;
|
||||
env.clearTimeout = fakeTimer.clearTimeout;
|
||||
env.setInterval = fakeTimer.setInterval;
|
||||
env.clearInterval = fakeTimer.clearInterval;
|
||||
});
|
||||
|
||||
describe('beforeEach', function() {
|
||||
it('should run before each spec for all suites', function () {
|
||||
var foo;
|
||||
env.beforeEach(function () {
|
||||
foo = 0;
|
||||
});
|
||||
|
||||
env.describe('suite 1', function () {
|
||||
env.it('test 1-1', function() {
|
||||
foo++;
|
||||
this.expect(foo).toEqual(1);
|
||||
});
|
||||
env.it('test 1-2', function() {
|
||||
foo++;
|
||||
this.expect(foo).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
env.describe('suite 2', function () {
|
||||
env.it('test 2-1', function() {
|
||||
foo++;
|
||||
this.expect(foo).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
env.currentRunner().execute();
|
||||
|
||||
var runnerResults = env.currentRunner().results();
|
||||
expect(runnerResults.totalCount).toEqual(3);
|
||||
expect(runnerResults.passedCount).toEqual(3);
|
||||
});
|
||||
|
||||
|
||||
it('should provide all specs', function () {
|
||||
var foo;
|
||||
env.beforeEach(function () {
|
||||
foo = 0;
|
||||
});
|
||||
|
||||
env.describe('suite 1', function () {
|
||||
env.it('test 1-1', function() {
|
||||
foo++;
|
||||
this.expect(foo).toEqual(1);
|
||||
});
|
||||
env.it('test 1-2', function() {
|
||||
foo++;
|
||||
this.expect(foo).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
env.describe('suite 2', function () {
|
||||
env.it('test 2-1', function() {
|
||||
foo++;
|
||||
this.expect(foo).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
env.currentRunner().execute();
|
||||
|
||||
|
||||
expect(env.currentRunner().specs().length).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('afterEach', function() {
|
||||
it('should run after each spec for all suites', function () {
|
||||
var foo = 3;
|
||||
env.afterEach(function () {
|
||||
foo = foo - 1;
|
||||
});
|
||||
|
||||
env.describe('suite 1', function () {
|
||||
env.it('test 1-1', function() {
|
||||
this.expect(foo).toEqual(3);
|
||||
});
|
||||
env.it('test 1-2', function() {
|
||||
this.expect(foo).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
env.describe('suite 2', function () {
|
||||
env.it('test 2-1', function() {
|
||||
this.expect(foo).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
env.currentRunner().execute();
|
||||
|
||||
var runnerResults = env.currentRunner().results();
|
||||
expect(runnerResults.totalCount).toEqual(3);
|
||||
expect(runnerResults.passedCount).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should run child suites and specs and generate results when execute is called', function() {
|
||||
env.describe('one suite description', function () {
|
||||
env.it('should be a test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.describe('another suite description', function () {
|
||||
env.it('should be another test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.currentRunner().execute();
|
||||
|
||||
var runnerResults = env.currentRunner().results();
|
||||
expect(runnerResults.totalCount).toEqual(2);
|
||||
expect(runnerResults.passedCount).toEqual(1);
|
||||
expect(runnerResults.failedCount).toEqual(1);
|
||||
});
|
||||
|
||||
|
||||
it('should ignore suites that have been x\'d', function() {
|
||||
env.xdescribe('one suite description', function () {
|
||||
env.it('should be a test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.describe('another suite description', function () {
|
||||
env.it('should be another test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.currentRunner().execute();
|
||||
|
||||
var runnerResults = env.currentRunner().results();
|
||||
expect(runnerResults.totalCount).toEqual(1);
|
||||
expect(runnerResults.passedCount).toEqual(0);
|
||||
expect(runnerResults.failedCount).toEqual(1);
|
||||
});
|
||||
|
||||
it('should roll up results from all specs', function() {
|
||||
env.describe('one suite description', function () {
|
||||
env.it('should be a test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.describe('another suite description', function () {
|
||||
env.it('should be another test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.currentRunner().execute();
|
||||
|
||||
var results = env.currentRunner().results();
|
||||
expect(results.totalCount).toEqual(2);
|
||||
expect(results.passedCount).toEqual(1);
|
||||
expect(results.failedCount).toEqual(1);
|
||||
});
|
||||
|
||||
describe('reporting', function () {
|
||||
var fakeReporter;
|
||||
beforeEach(function () {
|
||||
fakeReporter = jasmine.createSpyObj("fakeReporter", ["log", "reportRunnerStarting", "reportRunnerResults"]);
|
||||
env.addReporter(fakeReporter);
|
||||
});
|
||||
|
||||
it('should report runner results when the runner has completed running', function() {
|
||||
env.describe('one suite description', function () {
|
||||
env.it('should be a test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.describe('another suite description', function () {
|
||||
env.it('should be another test', function() {
|
||||
this.waits(200);
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.currentRunner().execute();
|
||||
expect(fakeReporter.reportRunnerResults).not.toHaveBeenCalled();
|
||||
fakeTimer.tick(200);
|
||||
//This blows up the JSApiReporter.
|
||||
//expect(fakeReporter.reportRunnerResults).toHaveBeenCalledWith(env.currentRunner);
|
||||
expect(fakeReporter.reportRunnerResults).toHaveBeenCalled();
|
||||
expect(fakeReporter.reportRunnerResults.mostRecentCall.args[0].results()).toEqual(env.currentRunner().results());
|
||||
});
|
||||
});
|
||||
|
||||
it("should report when the tests start running", function() {
|
||||
var fakeReporter = jasmine.createSpyObj("fakeReporter", ["log", "reportRunnerStarting"]);
|
||||
env.addReporter(fakeReporter);
|
||||
|
||||
|
||||
var runner = new jasmine.Runner(env);
|
||||
runner.arbitraryVariable = 'foo';
|
||||
spyOn(runner.queue, 'start');
|
||||
expect(fakeReporter.reportRunnerStarting).not.toHaveBeenCalled();
|
||||
runner.execute();
|
||||
expect(fakeReporter.reportRunnerStarting).toHaveBeenCalled();
|
||||
var reportedRunner = fakeReporter.reportRunnerStarting.mostRecentCall.args[0];
|
||||
expect(reportedRunner.arbitraryVariable).toEqual('foo');
|
||||
expect(runner.queue.start).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("when suites are nested", function() {
|
||||
var suite1, suite2, suite3;
|
||||
|
||||
function suiteNames(suites) {
|
||||
var suiteDescriptions = [];
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
suiteDescriptions.push(suites[i].getFullName());
|
||||
}
|
||||
return suiteDescriptions;
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
suite1 = env.describe("suite 1", function() {
|
||||
suite2 = env.describe("suite 2", function() {
|
||||
});
|
||||
});
|
||||
suite3 = env.describe("suite 3", function() {});
|
||||
});
|
||||
|
||||
it("#suites should return a flat array of all suites, including nested suites", function() {
|
||||
var suites = env.currentRunner().suites();
|
||||
expect(suiteNames(suites)).toEqual([suite1.getFullName(), suite2.getFullName(), suite3.getFullName()]);
|
||||
});
|
||||
|
||||
it("#topLevelSuites should return a flat array of all top-level suites only", function() {
|
||||
var suites = env.currentRunner().topLevelSuites();
|
||||
expect(suiteNames(suites)).toEqual([suite1.getFullName(), suite3.getFullName()]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,124 @@
|
||||
describe('Spec', function () {
|
||||
var env, suite;
|
||||
beforeEach(function() {
|
||||
env = new jasmine.Env();
|
||||
env.updateInterval = 0;
|
||||
suite = new jasmine.Suite(env, 'suite 1');
|
||||
});
|
||||
|
||||
describe('initialization', function () {
|
||||
|
||||
it('should raise an error if an env is not passed', function () {
|
||||
try {
|
||||
new jasmine.Spec();
|
||||
}
|
||||
catch (e) {
|
||||
expect(e.message).toEqual('jasmine.Env() required');
|
||||
}
|
||||
});
|
||||
|
||||
it('should raise an error if a suite is not passed', function () {
|
||||
try {
|
||||
new jasmine.Spec(env);
|
||||
}
|
||||
catch (e) {
|
||||
expect(e.message).toEqual('jasmine.Suite() required');
|
||||
}
|
||||
});
|
||||
|
||||
it('should assign sequential ids for specs belonging to the same env', function () {
|
||||
var spec1 = new jasmine.Spec(env, suite);
|
||||
var spec2 = new jasmine.Spec(env, suite);
|
||||
var spec3 = new jasmine.Spec(env, suite);
|
||||
expect(spec1.id).toEqual(0);
|
||||
expect(spec2.id).toEqual(1);
|
||||
expect(spec3.id).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
it('getFullName returns suite & spec description', function () {
|
||||
var spec = new jasmine.Spec(env, suite, 'spec 1');
|
||||
expect(spec.getFullName()).toEqual('suite 1 spec 1.')
|
||||
});
|
||||
|
||||
describe('results', function () {
|
||||
var spec, results;
|
||||
beforeEach(function () {
|
||||
spec = new jasmine.Spec(env, suite);
|
||||
results = spec.results();
|
||||
expect(results.totalCount).toEqual(0);
|
||||
spec.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('results shows the total number of expectations for each spec after execution', function () {
|
||||
expect(results.totalCount).toEqual(0);
|
||||
spec.execute();
|
||||
expect(results.totalCount).toEqual(2);
|
||||
});
|
||||
|
||||
it('results shows the number of passed expectations for each spec after execution', function () {
|
||||
expect(results.passedCount).toEqual(0);
|
||||
spec.execute();
|
||||
expect(results.passedCount).toEqual(2);
|
||||
});
|
||||
|
||||
it('results shows the number of failed expectations for each spec after execution', function () {
|
||||
spec.runs(function () {
|
||||
this.expect(true).toEqual(false);
|
||||
});
|
||||
expect(results.failedCount).toEqual(0);
|
||||
spec.execute();
|
||||
expect(results.failedCount).toEqual(1);
|
||||
});
|
||||
|
||||
describe('results.passed', function () {
|
||||
it('is true if all spec expectations pass', function () {
|
||||
spec.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
spec.execute();
|
||||
expect(results.passed()).toEqual(true);
|
||||
});
|
||||
|
||||
it('is false if one spec expectation fails', function () {
|
||||
spec.runs(function () {
|
||||
this.expect(true).toEqual(false);
|
||||
});
|
||||
spec.execute();
|
||||
expect(results.passed()).toEqual(false);
|
||||
});
|
||||
|
||||
it('a spec with no expectations will return true', function () {
|
||||
var specWithoutExpectations = new jasmine.Spec(env, suite);
|
||||
specWithoutExpectations.runs(function() {
|
||||
|
||||
});
|
||||
specWithoutExpectations.execute();
|
||||
expect(results.passed()).toEqual(true);
|
||||
});
|
||||
|
||||
it('an unexecuted spec will return true', function () {
|
||||
expect(results.passed()).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("includes log messages, which may contain arbitary objects", function() {
|
||||
spec.runs(function() {
|
||||
this.log("here's some log message", {key: 'value'}, 123);
|
||||
});
|
||||
spec.execute();
|
||||
var items = results.getItems();
|
||||
expect(items).toEqual([
|
||||
jasmine.any(jasmine.ExpectationResult),
|
||||
jasmine.any(jasmine.ExpectationResult),
|
||||
jasmine.any(jasmine.MessageResult)
|
||||
]);
|
||||
var logResult = items[2];
|
||||
expect(logResult.values).toEqual(["here's some log message", {key: 'value'}, 123]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,201 @@
|
||||
describe('Spies', function () {
|
||||
it('should replace the specified function with a spy object', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
}
|
||||
};
|
||||
this.spyOn(TestClass, 'someFunction');
|
||||
|
||||
expect(TestClass.someFunction.wasCalled).toEqual(false);
|
||||
expect(TestClass.someFunction.callCount).toEqual(0);
|
||||
TestClass.someFunction('foo');
|
||||
expect(TestClass.someFunction.wasCalled).toEqual(true);
|
||||
expect(TestClass.someFunction.callCount).toEqual(1);
|
||||
expect(TestClass.someFunction.mostRecentCall.args).toEqual(['foo']);
|
||||
expect(TestClass.someFunction.mostRecentCall.object).toEqual(TestClass);
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
|
||||
TestClass.someFunction('bar');
|
||||
expect(TestClass.someFunction.callCount).toEqual(2);
|
||||
expect(TestClass.someFunction.mostRecentCall.args).toEqual(['bar']);
|
||||
});
|
||||
|
||||
it('should allow you to view args for a particular call', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
}
|
||||
};
|
||||
this.spyOn(TestClass, 'someFunction');
|
||||
|
||||
TestClass.someFunction('foo');
|
||||
TestClass.someFunction('bar');
|
||||
expect(TestClass.someFunction.calls[0].args).toEqual(['foo']);
|
||||
expect(TestClass.someFunction.calls[1].args).toEqual(['bar']);
|
||||
expect(TestClass.someFunction.mostRecentCall.args).toEqual(['bar']);
|
||||
});
|
||||
|
||||
it('should be possible to call through to the original method, or return a specific result', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var passedArgs;
|
||||
var passedObj;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
passedArgs = arguments;
|
||||
passedObj = this;
|
||||
return "return value from original function";
|
||||
}
|
||||
};
|
||||
|
||||
this.spyOn(TestClass, 'someFunction').andCallThrough();
|
||||
var result = TestClass.someFunction('arg1', 'arg2');
|
||||
expect(result).toEqual("return value from original function");
|
||||
expect(originalFunctionWasCalled).toEqual(true);
|
||||
expect(passedArgs).toEqual(['arg1', 'arg2']);
|
||||
expect(passedObj).toEqual(TestClass);
|
||||
expect(TestClass.someFunction.wasCalled).toEqual(true);
|
||||
});
|
||||
|
||||
it('should be possible to return a specific value', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
return "return value from original function";
|
||||
}
|
||||
};
|
||||
|
||||
this.spyOn(TestClass, 'someFunction').andReturn("some value");
|
||||
originalFunctionWasCalled = false;
|
||||
var result = TestClass.someFunction('arg1', 'arg2');
|
||||
expect(result).toEqual("some value");
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
});
|
||||
|
||||
it('should be possible to throw a specific error', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
return "return value from original function";
|
||||
}
|
||||
};
|
||||
|
||||
this.spyOn(TestClass, 'someFunction').andThrow(new Error('fake error'));
|
||||
var exception;
|
||||
try {
|
||||
TestClass.someFunction('arg1', 'arg2');
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
expect(exception.message).toEqual('fake error');
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
});
|
||||
|
||||
it('should be possible to call a specified function', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var fakeFunctionWasCalled = false;
|
||||
var passedArgs;
|
||||
var passedObj;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
return "return value from original function";
|
||||
}
|
||||
};
|
||||
|
||||
this.spyOn(TestClass, 'someFunction').andCallFake(function() {
|
||||
fakeFunctionWasCalled = true;
|
||||
passedArgs = arguments;
|
||||
passedObj = this;
|
||||
return "return value from fake function";
|
||||
});
|
||||
|
||||
var result = TestClass.someFunction('arg1', 'arg2');
|
||||
expect(result).toEqual("return value from fake function");
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
expect(fakeFunctionWasCalled).toEqual(true);
|
||||
expect(passedArgs).toEqual(['arg1', 'arg2']);
|
||||
expect(passedObj).toEqual(TestClass);
|
||||
expect(TestClass.someFunction.wasCalled).toEqual(true);
|
||||
});
|
||||
|
||||
it('is torn down when this.removeAllSpies is called', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
}
|
||||
};
|
||||
this.spyOn(TestClass, 'someFunction');
|
||||
|
||||
TestClass.someFunction('foo');
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
|
||||
this.removeAllSpies();
|
||||
|
||||
TestClass.someFunction('foo');
|
||||
expect(originalFunctionWasCalled).toEqual(true);
|
||||
});
|
||||
|
||||
it('calls removeAllSpies during spec finish', function() {
|
||||
var test = new jasmine.Spec(new jasmine.Env(), {}, 'sample test');
|
||||
|
||||
this.spyOn(test, 'removeAllSpies');
|
||||
|
||||
test.finish();
|
||||
|
||||
expect(test.removeAllSpies).wasCalled();
|
||||
});
|
||||
|
||||
it('throws an exception when some method is spied on twice', function() {
|
||||
var TestClass = { someFunction: function() {
|
||||
} };
|
||||
this.spyOn(TestClass, 'someFunction');
|
||||
var exception;
|
||||
try {
|
||||
this.spyOn(TestClass, 'someFunction');
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
expect(exception).toBeDefined();
|
||||
});
|
||||
|
||||
it('should be able to reset a spy', function() {
|
||||
var TestClass = { someFunction: function() {} };
|
||||
this.spyOn(TestClass, 'someFunction');
|
||||
|
||||
expect(TestClass.someFunction).not.toHaveBeenCalled();
|
||||
TestClass.someFunction();
|
||||
expect(TestClass.someFunction).toHaveBeenCalled();
|
||||
TestClass.someFunction.reset();
|
||||
expect(TestClass.someFunction).not.toHaveBeenCalled();
|
||||
expect(TestClass.someFunction.callCount).toEqual(0);
|
||||
});
|
||||
|
||||
describe("createSpyObj", function() {
|
||||
it("should create an object with a bunch of spy methods when you call jasmine.createSpyObj()", function() {
|
||||
var spyObj = jasmine.createSpyObj('BaseName', ['method1', 'method2']);
|
||||
expect(spyObj).toEqual({ method1: jasmine.any(Function), method2: jasmine.any(Function)});
|
||||
expect(spyObj.method1.identity).toEqual('BaseName.method1');
|
||||
expect(spyObj.method2.identity).toEqual('BaseName.method2');
|
||||
});
|
||||
|
||||
it("should throw if you do not pass an array argument", function() {
|
||||
expect(function() {
|
||||
jasmine.createSpyObj('BaseName');
|
||||
}).toThrow('createSpyObj requires a non-empty array of method names to create spies for');
|
||||
});
|
||||
|
||||
it("should throw if you pass an empty array argument", function() {
|
||||
expect(function() {
|
||||
jasmine.createSpyObj('BaseName');
|
||||
}).toThrow('createSpyObj requires a non-empty array of method names to create spies for');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,120 @@
|
||||
describe('Suite', function() {
|
||||
var fakeTimer;
|
||||
var env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmine.Env();
|
||||
env.updateInterval = 0;
|
||||
|
||||
fakeTimer = new jasmine.FakeTimer();
|
||||
env.setTimeout = fakeTimer.setTimeout;
|
||||
env.clearTimeout = fakeTimer.clearTimeout;
|
||||
env.setInterval = fakeTimer.setInterval;
|
||||
env.clearInterval = fakeTimer.clearInterval;
|
||||
});
|
||||
|
||||
describe('Specs', function () {
|
||||
var suite;
|
||||
|
||||
beforeEach(function() {
|
||||
suite = env.describe('Suite 1', function () {
|
||||
env.it('Spec 1', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
env.it('Spec 2', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
env.describe('Suite 2', function () {
|
||||
env.it('Spec 3', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
env.it('Spec 4', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('#specs should return all immediate children that are specs.', function () {
|
||||
var suiteSpecs = suite.specs();
|
||||
expect(suiteSpecs.length).toEqual(3);
|
||||
expect(suiteSpecs[0].description).toEqual('Spec 1');
|
||||
expect(suiteSpecs[1].description).toEqual('Spec 2');
|
||||
expect(suiteSpecs[2].description).toEqual('Spec 4');
|
||||
});
|
||||
|
||||
it("#suites should return all immediate children that are suites.", function() {
|
||||
var nestedSuites = suite.suites();
|
||||
expect(nestedSuites.length).toEqual(1);
|
||||
expect(nestedSuites[0].description).toEqual('Suite 2');
|
||||
});
|
||||
|
||||
it("#children should return all immediate children including suites and specs.", function() {
|
||||
var children = suite.children();
|
||||
expect(children.length).toEqual(4);
|
||||
expect(children[0].description).toEqual('Spec 1');
|
||||
expect(children[1].description).toEqual('Spec 2');
|
||||
expect(children[2].description).toEqual('Suite 2');
|
||||
expect(children[3].description).toEqual('Spec 4');
|
||||
});
|
||||
});
|
||||
|
||||
describe('SpecCount', function () {
|
||||
|
||||
it('should keep a count of the number of specs that are run', function() {
|
||||
var suite = env.describe('one suite description', function () {
|
||||
env.it('should be a test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
env.it('should be another test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
env.it('should be a third test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
expect(suite.specs().length).toEqual(3);
|
||||
});
|
||||
|
||||
it('specCount should be correct even with runs/waits blocks', function() {
|
||||
var suite = env.describe('one suite description', function () {
|
||||
env.it('should be a test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
env.it('should be another test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
this.waits(10);
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
env.it('should be a third test', function() {
|
||||
this.runs(function () {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
expect(suite.specs().length).toEqual(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,235 @@
|
||||
describe("TrivialReporter", function() {
|
||||
var env;
|
||||
var trivialReporter;
|
||||
var body;
|
||||
var fakeDocument;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmine.Env();
|
||||
env.updateInterval = 0;
|
||||
|
||||
body = document.createElement("body");
|
||||
fakeDocument = { body: body, location: { search: "" } };
|
||||
trivialReporter = new jasmine.TrivialReporter(fakeDocument);
|
||||
});
|
||||
|
||||
function fakeSpec(name) {
|
||||
return {
|
||||
getFullName: function() {
|
||||
return name;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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() {
|
||||
fakeDocument.location.search = "?spec=run%20this";
|
||||
expect(trivialReporter.specFilter(fakeSpec("run this"))).toBeTruthy();
|
||||
expect(trivialReporter.specFilter(fakeSpec("not the right spec"))).toBeFalsy();
|
||||
expect(trivialReporter.specFilter(fakeSpec("not run this"))).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should display empty divs for every suite when the runner is starting", function() {
|
||||
trivialReporter.reportRunnerStarting({
|
||||
env: env,
|
||||
suites: function() {
|
||||
return [ new jasmine.Suite({}, "suite 1", null, null) ];
|
||||
}
|
||||
});
|
||||
|
||||
var divs = findElements(body.getElementsByTagName("div"), "suite");
|
||||
expect(divs.length).toEqual(1);
|
||||
expect(divs[0].innerHTML).toContain("suite 1");
|
||||
});
|
||||
|
||||
describe('Matcher reporting', function () {
|
||||
var getResultMessageDiv = function (body) {
|
||||
var divs = body.getElementsByTagName("div");
|
||||
for (var i = 0; i < divs.length; i++) {
|
||||
if (divs[i].className.match(/resultMessage/)) {
|
||||
return divs[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var runner, spec, fakeTimer;
|
||||
beforeEach(function () {
|
||||
fakeTimer = new jasmine.FakeTimer();
|
||||
env.setTimeout = fakeTimer.setTimeout;
|
||||
env.clearTimeout = fakeTimer.clearTimeout;
|
||||
env.setInterval = fakeTimer.setInterval;
|
||||
env.clearInterval = fakeTimer.clearInterval;
|
||||
runner = env.currentRunner();
|
||||
var suite = new jasmine.Suite(env, 'some suite');
|
||||
runner.add(suite);
|
||||
spec = new jasmine.Spec(env, suite, 'some spec');
|
||||
suite.add(spec);
|
||||
fakeDocument.location.search = "?";
|
||||
env.addReporter(trivialReporter);
|
||||
});
|
||||
|
||||
describe('toContain', function () {
|
||||
it('should show actual and expected', function () {
|
||||
spec.runs(function () {
|
||||
this.expect('foo').toContain('bar');
|
||||
});
|
||||
runner.execute();
|
||||
fakeTimer.tick(0);
|
||||
|
||||
var resultEl = getResultMessageDiv(body);
|
||||
expect(resultEl.innerHTML).toMatch(/foo/);
|
||||
expect(resultEl.innerHTML).toMatch(/bar/);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("failure messages (integration)", function () {
|
||||
var spec, results, expectationResult;
|
||||
|
||||
beforeEach(function() {
|
||||
results = {
|
||||
passed: function() {
|
||||
return false;
|
||||
},
|
||||
getItems: function() {
|
||||
}};
|
||||
|
||||
var suite1 = new jasmine.Suite(env, "suite 1", null, null);
|
||||
|
||||
spec = {
|
||||
suite: suite1,
|
||||
getFullName: function() {
|
||||
return "foo";
|
||||
},
|
||||
results: function() {
|
||||
return results;
|
||||
}
|
||||
};
|
||||
|
||||
trivialReporter.reportRunnerStarting({
|
||||
env: env,
|
||||
suites: function() {
|
||||
return [ suite1 ];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should add the failure message to the DOM (non-toEquals matchers)", function() {
|
||||
expectationResult = new jasmine.ExpectationResult({
|
||||
matcherName: "toBeNull", passed: false, message: "Expected 'a' to be null, but it was not"
|
||||
});
|
||||
|
||||
spyOn(results, 'getItems').andReturn([expectationResult]);
|
||||
|
||||
trivialReporter.reportSpecResults(spec);
|
||||
|
||||
var divs = body.getElementsByTagName("div");
|
||||
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) html escaping", function() {
|
||||
expectationResult = new jasmine.ExpectationResult({
|
||||
matcherName: "toBeNull", passed: false, message: "Expected '1 < 2' to <b>e null, & it was not"
|
||||
});
|
||||
|
||||
spyOn(results, 'getItems').andReturn([expectationResult]);
|
||||
|
||||
trivialReporter.reportSpecResults(spec);
|
||||
|
||||
var divs = body.getElementsByTagName("div");
|
||||
var errorDiv = findElement(divs, 'resultMessage fail');
|
||||
expect(errorDiv.innerHTML).toEqual("Expected '1 < 2' to <b>e null, & it was not");
|
||||
});
|
||||
});
|
||||
|
||||
describe("log messages", function() {
|
||||
it("should appear in the report", function() {
|
||||
env.describe("suite", function() {
|
||||
env.it("will have log messages", function() {
|
||||
this.log("this is a", "multipart log message");
|
||||
});
|
||||
});
|
||||
|
||||
env.addReporter(trivialReporter);
|
||||
env.execute();
|
||||
|
||||
var divs = body.getElementsByTagName("div");
|
||||
var errorDiv = findElement(divs, 'resultMessage log');
|
||||
expect(errorDiv.innerHTML).toEqual("this is a multipart log message");
|
||||
});
|
||||
});
|
||||
|
||||
describe("duplicate example names", function() {
|
||||
it("should report failures correctly", function() {
|
||||
var suite1 = env.describe("suite", function() {
|
||||
env.it("will have log messages", function() {
|
||||
this.log("this one fails!");
|
||||
this.expect(true).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
var suite2 = env.describe("suite", function() {
|
||||
env.it("will have log messages", function() {
|
||||
this.log("this one passes!");
|
||||
this.expect(true).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
env.addReporter(trivialReporter);
|
||||
env.execute();
|
||||
|
||||
var divs = body.getElementsByTagName("div");
|
||||
var passedSpecDiv = findElement(divs, 'suite passed');
|
||||
expect(passedSpecDiv.className).toEqual('suite passed');
|
||||
expect(passedSpecDiv.innerHTML).toContain("this one passes!");
|
||||
expect(passedSpecDiv.innerHTML).not.toContain("this one fails!");
|
||||
|
||||
var failedSpecDiv = findElement(divs, 'suite failed');
|
||||
expect(failedSpecDiv.className).toEqual('suite failed');
|
||||
expect(failedSpecDiv.innerHTML).toContain("this one fails!");
|
||||
expect(failedSpecDiv.innerHTML).not.toContain("this one passes!");
|
||||
});
|
||||
});
|
||||
|
||||
describe('#reportSpecStarting', function() {
|
||||
var spec1;
|
||||
beforeEach(function () {
|
||||
env.describe("suite 1", function() {
|
||||
spec1 = env.it("spec 1", function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('DOES NOT log running specs by default', function() {
|
||||
spyOn(trivialReporter, 'log');
|
||||
|
||||
trivialReporter.reportSpecStarting(spec1);
|
||||
|
||||
expect(trivialReporter.log).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('logs running specs when log_running_specs is true', function() {
|
||||
trivialReporter.logRunningSpecs = true;
|
||||
spyOn(trivialReporter, 'log');
|
||||
|
||||
trivialReporter.reportSpecStarting(spec1);
|
||||
|
||||
expect(trivialReporter.log).toHaveBeenCalledWith('>> Jasmine Running suite 1 spec 1...');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
describe("jasmine.util", function() {
|
||||
describe("extend", function () {
|
||||
it("should add properies to a destination object ", function() {
|
||||
var destination = {baz: 'baz'};
|
||||
jasmine.util.extend(destination, {
|
||||
foo: 'foo', bar: 'bar'
|
||||
});
|
||||
expect(destination).toEqual({foo: 'foo', bar: 'bar', baz: 'baz'});
|
||||
});
|
||||
|
||||
it("should replace properies that already exist on a destination object", function() {
|
||||
var destination = {foo: 'foo'};
|
||||
jasmine.util.extend(destination, {
|
||||
foo: 'bar'
|
||||
});
|
||||
expect(destination).toEqual({foo: 'bar'});
|
||||
jasmine.util.extend(destination, {
|
||||
foo: null
|
||||
});
|
||||
expect(destination).toEqual({foo: null});
|
||||
});
|
||||
});
|
||||
|
||||
describe("isArray_", function() {
|
||||
it("should return true if the argument is an array", function() {
|
||||
expect(jasmine.isArray_([])).toBe(true);
|
||||
expect(jasmine.isArray_(['a'])).toBe(true);
|
||||
expect(jasmine.isArray_(new Array())).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false if the argument is not an array", function() {
|
||||
expect(jasmine.isArray_(undefined)).toBe(false);
|
||||
expect(jasmine.isArray_({})).toBe(false);
|
||||
expect(jasmine.isArray_(function() {})).toBe(false);
|
||||
expect(jasmine.isArray_('foo')).toBe(false);
|
||||
expect(jasmine.isArray_(5)).toBe(false);
|
||||
expect(jasmine.isArray_(null)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,87 @@
|
||||
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).not.toHaveBeenCalled();
|
||||
block.execute(onComplete);
|
||||
expect(onComplete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
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).toHaveBeenCalledWith('some error');
|
||||
expect(onComplete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
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 10 ms', function () {
|
||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
||||
expect(latchFunction).not.toHaveBeenCalled();
|
||||
block.execute(onComplete);
|
||||
expect(latchFunction.callCount).toEqual(1);
|
||||
fakeTimer.tick(5);
|
||||
expect(latchFunction.callCount).toEqual(1);
|
||||
fakeTimer.tick(5);
|
||||
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).not.toHaveBeenCalled();
|
||||
block.execute(onComplete);
|
||||
expect(onComplete).not.toHaveBeenCalled();
|
||||
latchFunction.andReturn(true);
|
||||
fakeTimer.tick(100);
|
||||
expect(onComplete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
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).not.toHaveBeenCalled();
|
||||
fakeTimer.tick(timeout);
|
||||
expect(spec.fail).toHaveBeenCalled();
|
||||
var failMessage = spec.fail.mostRecentCall.args[0].message;
|
||||
expect(failMessage).toMatch(message);
|
||||
expect(onComplete).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Blocks are functions with executable code that make up a spec.
|
||||
*
|
||||
* @constructor
|
||||
* @param {jasmine.Env} env
|
||||
* @param {Function} func
|
||||
* @param {jasmine.Spec} spec
|
||||
*/
|
||||
jasmine.Block = function(env, func, spec) {
|
||||
this.env = env;
|
||||
this.func = func;
|
||||
this.spec = spec;
|
||||
};
|
||||
|
||||
jasmine.Block.prototype.execute = function(onComplete) {
|
||||
try {
|
||||
this.func.apply(this.spec);
|
||||
} catch (e) {
|
||||
this.spec.fail(e);
|
||||
}
|
||||
onComplete();
|
||||
};
|
||||
@@ -0,0 +1,264 @@
|
||||
/**
|
||||
* Environment for Jasmine
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
jasmine.Env = function() {
|
||||
this.currentSpec = null;
|
||||
this.currentSuite = null;
|
||||
this.currentRunner_ = new jasmine.Runner(this);
|
||||
|
||||
this.reporter = new jasmine.MultiReporter();
|
||||
|
||||
this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
|
||||
this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
|
||||
this.lastUpdate = 0;
|
||||
this.specFilter = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
this.nextSpecId_ = 0;
|
||||
this.nextSuiteId_ = 0;
|
||||
this.equalityTesters_ = [];
|
||||
|
||||
// wrap matchers
|
||||
this.matchersClass = function() {
|
||||
jasmine.Matchers.apply(this, arguments);
|
||||
};
|
||||
jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
|
||||
|
||||
jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
|
||||
};
|
||||
|
||||
|
||||
jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
|
||||
jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
|
||||
jasmine.Env.prototype.setInterval = jasmine.setInterval;
|
||||
jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
|
||||
|
||||
/**
|
||||
* @returns an object containing jasmine version build info, if set.
|
||||
*/
|
||||
jasmine.Env.prototype.version = function () {
|
||||
if (jasmine.version_) {
|
||||
return jasmine.version_;
|
||||
} else {
|
||||
throw new Error('Version not set');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
jasmine.Env.prototype.nextSpecId = function () {
|
||||
return this.nextSpecId_++;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns a sequential integer starting at 0
|
||||
*/
|
||||
jasmine.Env.prototype.nextSuiteId = function () {
|
||||
return this.nextSuiteId_++;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register a reporter to receive status updates from Jasmine.
|
||||
* @param {jasmine.Reporter} reporter An object which will receive status updates.
|
||||
*/
|
||||
jasmine.Env.prototype.addReporter = function(reporter) {
|
||||
this.reporter.addReporter(reporter);
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.execute = function() {
|
||||
this.currentRunner_.execute();
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.describe = function(description, specDefinitions) {
|
||||
var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
|
||||
|
||||
var parentSuite = this.currentSuite;
|
||||
if (parentSuite) {
|
||||
parentSuite.add(suite);
|
||||
} else {
|
||||
this.currentRunner_.add(suite);
|
||||
}
|
||||
|
||||
this.currentSuite = 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;
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
|
||||
if (this.currentSuite) {
|
||||
this.currentSuite.beforeEach(beforeEachFunction);
|
||||
} else {
|
||||
this.currentRunner_.beforeEach(beforeEachFunction);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.currentRunner = function () {
|
||||
return this.currentRunner_;
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.afterEach = function(afterEachFunction) {
|
||||
if (this.currentSuite) {
|
||||
this.currentSuite.afterEach(afterEachFunction);
|
||||
} else {
|
||||
this.currentRunner_.afterEach(afterEachFunction);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
|
||||
return {
|
||||
execute: function() {
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.it = function(description, func) {
|
||||
var spec = new jasmine.Spec(this, this.currentSuite, description);
|
||||
this.currentSuite.add(spec);
|
||||
this.currentSpec = spec;
|
||||
|
||||
if (func) {
|
||||
spec.runs(func);
|
||||
}
|
||||
|
||||
return spec;
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.xit = function(desc, func) {
|
||||
return {
|
||||
id: this.nextSpecId(),
|
||||
runs: function() {
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
|
||||
if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
|
||||
return true;
|
||||
}
|
||||
|
||||
a.__Jasmine_been_here_before__ = b;
|
||||
b.__Jasmine_been_here_before__ = a;
|
||||
|
||||
var hasKey = function(obj, keyName) {
|
||||
return obj != null && obj[keyName] !== jasmine.undefined;
|
||||
};
|
||||
|
||||
for (var property in b) {
|
||||
if (!hasKey(a, property) && hasKey(b, property)) {
|
||||
mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
|
||||
}
|
||||
}
|
||||
for (property in a) {
|
||||
if (!hasKey(b, property) && hasKey(a, property)) {
|
||||
mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
|
||||
}
|
||||
}
|
||||
for (property in b) {
|
||||
if (property == '__Jasmine_been_here_before__') continue;
|
||||
if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
|
||||
mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual.");
|
||||
}
|
||||
}
|
||||
|
||||
if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
|
||||
mismatchValues.push("arrays were not the same length");
|
||||
}
|
||||
|
||||
delete a.__Jasmine_been_here_before__;
|
||||
delete b.__Jasmine_been_here_before__;
|
||||
return (mismatchKeys.length == 0 && mismatchValues.length == 0);
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
|
||||
mismatchKeys = mismatchKeys || [];
|
||||
mismatchValues = mismatchValues || [];
|
||||
|
||||
for (var i = 0; i < this.equalityTesters_.length; i++) {
|
||||
var equalityTester = this.equalityTesters_[i];
|
||||
var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
|
||||
if (result !== jasmine.undefined) return result;
|
||||
}
|
||||
|
||||
if (a === b) return true;
|
||||
|
||||
if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
|
||||
return (a == jasmine.undefined && b == jasmine.undefined);
|
||||
}
|
||||
|
||||
if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
if (a instanceof Date && b instanceof Date) {
|
||||
return a.getTime() == b.getTime();
|
||||
}
|
||||
|
||||
if (a instanceof jasmine.Matchers.Any) {
|
||||
return a.matches(b);
|
||||
}
|
||||
|
||||
if (b instanceof jasmine.Matchers.Any) {
|
||||
return b.matches(a);
|
||||
}
|
||||
|
||||
if (jasmine.isString_(a) && jasmine.isString_(b)) {
|
||||
return (a == b);
|
||||
}
|
||||
|
||||
if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
|
||||
return (a == b);
|
||||
}
|
||||
|
||||
if (typeof a === "object" && typeof b === "object") {
|
||||
return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
|
||||
}
|
||||
|
||||
//Straight check
|
||||
return (a === b);
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.contains_ = function(haystack, needle) {
|
||||
if (jasmine.isArray_(haystack)) {
|
||||
for (var i = 0; i < haystack.length; i++) {
|
||||
if (this.equals_(haystack[i], needle)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return haystack.indexOf(needle) >= 0;
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
|
||||
this.equalityTesters_.push(equalityTester);
|
||||
};
|
||||
@@ -0,0 +1,102 @@
|
||||
/** JavaScript API reporter.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
jasmine.JsApiReporter = function() {
|
||||
this.started = false;
|
||||
this.finished = false;
|
||||
this.suites_ = [];
|
||||
this.results_ = {};
|
||||
};
|
||||
|
||||
jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
|
||||
this.started = true;
|
||||
var suites = runner.topLevelSuites();
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
var suite = suites[i];
|
||||
this.suites_.push(this.summarize_(suite));
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.JsApiReporter.prototype.suites = function() {
|
||||
return this.suites_;
|
||||
};
|
||||
|
||||
jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
|
||||
var isSuite = suiteOrSpec instanceof jasmine.Suite;
|
||||
var summary = {
|
||||
id: suiteOrSpec.id,
|
||||
name: suiteOrSpec.description,
|
||||
type: isSuite ? 'suite' : 'spec',
|
||||
children: []
|
||||
};
|
||||
|
||||
if (isSuite) {
|
||||
var children = suiteOrSpec.children();
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
summary.children.push(this.summarize_(children[i]));
|
||||
}
|
||||
}
|
||||
return summary;
|
||||
};
|
||||
|
||||
jasmine.JsApiReporter.prototype.results = function() {
|
||||
return this.results_;
|
||||
};
|
||||
|
||||
jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
|
||||
return this.results_[specId];
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
|
||||
this.finished = true;
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
|
||||
this.results_[spec.id] = {
|
||||
messages: spec.results().getItems(),
|
||||
result: spec.results().failedCount > 0 ? "failed" : "passed"
|
||||
};
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
jasmine.JsApiReporter.prototype.log = function(str) {
|
||||
};
|
||||
|
||||
jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
|
||||
var results = {};
|
||||
for (var i = 0; i < specIds.length; i++) {
|
||||
var specId = specIds[i];
|
||||
results[specId] = this.summarizeResult_(this.results_[specId]);
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
|
||||
var summaryMessages = [];
|
||||
var messagesLength = result.messages.length;
|
||||
for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
|
||||
var resultMessage = result.messages[messageIndex];
|
||||
summaryMessages.push({
|
||||
text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
|
||||
passed: resultMessage.passed ? resultMessage.passed() : true,
|
||||
type: resultMessage.type,
|
||||
message: resultMessage.message,
|
||||
trace: {
|
||||
stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
result : result.result,
|
||||
messages : summaryMessages
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
/**
|
||||
* @constructor
|
||||
* @param {jasmine.Env} env
|
||||
* @param actual
|
||||
* @param {jasmine.Spec} spec
|
||||
*/
|
||||
jasmine.Matchers = function(env, actual, spec, opt_isNot) {
|
||||
this.env = env;
|
||||
this.actual = actual;
|
||||
this.spec = spec;
|
||||
this.isNot = opt_isNot || false;
|
||||
this.reportWasCalled_ = false;
|
||||
};
|
||||
|
||||
// todo: @deprecated as of Jasmine 0.11, remove soon [xw]
|
||||
jasmine.Matchers.pp = function(str) {
|
||||
throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
|
||||
};
|
||||
|
||||
// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
|
||||
jasmine.Matchers.prototype.report = function(result, failing_message, details) {
|
||||
throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
|
||||
};
|
||||
|
||||
jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
|
||||
for (var methodName in prototype) {
|
||||
if (methodName == 'report') continue;
|
||||
var orig = prototype[methodName];
|
||||
matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
|
||||
return function() {
|
||||
var matcherArgs = jasmine.util.argsToArray(arguments);
|
||||
var result = matcherFunction.apply(this, arguments);
|
||||
|
||||
if (this.isNot) {
|
||||
result = !result;
|
||||
}
|
||||
|
||||
if (this.reportWasCalled_) return result;
|
||||
|
||||
var message;
|
||||
if (!result) {
|
||||
if (this.message) {
|
||||
message = this.message.apply(this, arguments);
|
||||
if (jasmine.isArray_(message)) {
|
||||
message = message[this.isNot ? 1 : 0];
|
||||
}
|
||||
} else {
|
||||
var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
|
||||
message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
|
||||
if (matcherArgs.length > 0) {
|
||||
for (var i = 0; i < matcherArgs.length; i++) {
|
||||
if (i > 0) message += ",";
|
||||
message += " " + jasmine.pp(matcherArgs[i]);
|
||||
}
|
||||
}
|
||||
message += ".";
|
||||
}
|
||||
}
|
||||
var expectationResult = new jasmine.ExpectationResult({
|
||||
matcherName: matcherName,
|
||||
passed: result,
|
||||
expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
|
||||
actual: this.actual,
|
||||
message: message
|
||||
});
|
||||
this.spec.addMatcherResult(expectationResult);
|
||||
return jasmine.undefined;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* toBe: compares the actual to the expected using ===
|
||||
* @param expected
|
||||
*/
|
||||
jasmine.Matchers.prototype.toBe = function(expected) {
|
||||
return this.actual === expected;
|
||||
};
|
||||
|
||||
/**
|
||||
* toNotBe: compares the actual to the expected using !==
|
||||
* @param expected
|
||||
* @deprecated as of 1.0. Use not.toBe() instead.
|
||||
*/
|
||||
jasmine.Matchers.prototype.toNotBe = function(expected) {
|
||||
return this.actual !== expected;
|
||||
};
|
||||
|
||||
/**
|
||||
* toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
|
||||
*
|
||||
* @param expected
|
||||
*/
|
||||
jasmine.Matchers.prototype.toEqual = function(expected) {
|
||||
return this.env.equals_(this.actual, expected);
|
||||
};
|
||||
|
||||
/**
|
||||
* toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
|
||||
* @param expected
|
||||
* @deprecated as of 1.0. Use not.toNotEqual() instead.
|
||||
*/
|
||||
jasmine.Matchers.prototype.toNotEqual = function(expected) {
|
||||
return !this.env.equals_(this.actual, expected);
|
||||
};
|
||||
|
||||
/**
|
||||
* Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes
|
||||
* a pattern or a String.
|
||||
*
|
||||
* @param expected
|
||||
*/
|
||||
jasmine.Matchers.prototype.toMatch = function(expected) {
|
||||
return new RegExp(expected).test(this.actual);
|
||||
};
|
||||
|
||||
/**
|
||||
* Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
|
||||
* @param expected
|
||||
* @deprecated as of 1.0. Use not.toMatch() instead.
|
||||
*/
|
||||
jasmine.Matchers.prototype.toNotMatch = function(expected) {
|
||||
return !(new RegExp(expected).test(this.actual));
|
||||
};
|
||||
|
||||
/**
|
||||
* Matcher that compares the actual to jasmine.undefined.
|
||||
*/
|
||||
jasmine.Matchers.prototype.toBeDefined = function() {
|
||||
return (this.actual !== jasmine.undefined);
|
||||
};
|
||||
|
||||
/**
|
||||
* Matcher that compares the actual to jasmine.undefined.
|
||||
*/
|
||||
jasmine.Matchers.prototype.toBeUndefined = function() {
|
||||
return (this.actual === jasmine.undefined);
|
||||
};
|
||||
|
||||
/**
|
||||
* Matcher that compares the actual to null.
|
||||
*/
|
||||
jasmine.Matchers.prototype.toBeNull = function() {
|
||||
return (this.actual === null);
|
||||
};
|
||||
|
||||
/**
|
||||
* Matcher that boolean not-nots the actual.
|
||||
*/
|
||||
jasmine.Matchers.prototype.toBeTruthy = function() {
|
||||
return !!this.actual;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Matcher that boolean nots the actual.
|
||||
*/
|
||||
jasmine.Matchers.prototype.toBeFalsy = function() {
|
||||
return !this.actual;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Matcher that checks to see if the actual, a Jasmine spy, was called.
|
||||
*/
|
||||
jasmine.Matchers.prototype.toHaveBeenCalled = function() {
|
||||
if (arguments.length > 0) {
|
||||
throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
|
||||
}
|
||||
|
||||
if (!jasmine.isSpy(this.actual)) {
|
||||
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
|
||||
}
|
||||
|
||||
this.message = function() {
|
||||
return [
|
||||
"Expected spy " + this.actual.identity + " to have been called.",
|
||||
"Expected spy " + this.actual.identity + " not to have been called."
|
||||
];
|
||||
};
|
||||
|
||||
return this.actual.wasCalled;
|
||||
};
|
||||
|
||||
/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
|
||||
jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
|
||||
|
||||
/**
|
||||
* Matcher that checks to see if the actual, a Jasmine spy, was not called.
|
||||
*
|
||||
* @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
|
||||
*/
|
||||
jasmine.Matchers.prototype.wasNotCalled = function() {
|
||||
if (arguments.length > 0) {
|
||||
throw new Error('wasNotCalled does not take arguments');
|
||||
}
|
||||
|
||||
if (!jasmine.isSpy(this.actual)) {
|
||||
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
|
||||
}
|
||||
|
||||
this.message = function() {
|
||||
return [
|
||||
"Expected spy " + this.actual.identity + " to not have been called.",
|
||||
"Expected spy " + this.actual.identity + " to have been called."
|
||||
];
|
||||
};
|
||||
|
||||
return !this.actual.wasCalled;
|
||||
};
|
||||
|
||||
/**
|
||||
* Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
*/
|
||||
jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
|
||||
var expectedArgs = jasmine.util.argsToArray(arguments);
|
||||
if (!jasmine.isSpy(this.actual)) {
|
||||
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
|
||||
}
|
||||
this.message = function() {
|
||||
if (this.actual.callCount == 0) {
|
||||
// todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
|
||||
return [
|
||||
"Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
|
||||
"Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
"Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
|
||||
"Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
return this.env.contains_(this.actual.argsForCall, expectedArgs);
|
||||
};
|
||||
|
||||
/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
|
||||
jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
|
||||
|
||||
/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
|
||||
jasmine.Matchers.prototype.wasNotCalledWith = function() {
|
||||
var expectedArgs = jasmine.util.argsToArray(arguments);
|
||||
if (!jasmine.isSpy(this.actual)) {
|
||||
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
|
||||
}
|
||||
|
||||
this.message = function() {
|
||||
return [
|
||||
"Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
|
||||
"Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
|
||||
]
|
||||
};
|
||||
|
||||
return !this.env.contains_(this.actual.argsForCall, expectedArgs);
|
||||
};
|
||||
|
||||
/**
|
||||
* Matcher that checks that the expected item is an element in the actual Array.
|
||||
*
|
||||
* @param {Object} expected
|
||||
*/
|
||||
jasmine.Matchers.prototype.toContain = function(expected) {
|
||||
return this.env.contains_(this.actual, expected);
|
||||
};
|
||||
|
||||
/**
|
||||
* Matcher that checks that the expected item is NOT an element in the actual Array.
|
||||
*
|
||||
* @param {Object} expected
|
||||
* @deprecated as of 1.0. Use not.toNotContain() instead.
|
||||
*/
|
||||
jasmine.Matchers.prototype.toNotContain = function(expected) {
|
||||
return !this.env.contains_(this.actual, expected);
|
||||
};
|
||||
|
||||
jasmine.Matchers.prototype.toBeLessThan = function(expected) {
|
||||
return this.actual < expected;
|
||||
};
|
||||
|
||||
jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
|
||||
return this.actual > expected;
|
||||
};
|
||||
|
||||
/**
|
||||
* Matcher that checks that the expected exception was thrown by the actual.
|
||||
*
|
||||
* @param {String} expected
|
||||
*/
|
||||
jasmine.Matchers.prototype.toThrow = function(expected) {
|
||||
var result = false;
|
||||
var exception;
|
||||
if (typeof this.actual != 'function') {
|
||||
throw new Error('Actual is not a function');
|
||||
}
|
||||
try {
|
||||
this.actual();
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
if (exception) {
|
||||
result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
|
||||
}
|
||||
|
||||
var not = this.isNot ? "not " : "";
|
||||
|
||||
this.message = function() {
|
||||
if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
|
||||
return ["Expected function " + not + "to throw", expected ? expected.message || expected : " an exception", ", but it threw", exception.message || exception].join(' ');
|
||||
} else {
|
||||
return "Expected function to throw an exception.";
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
jasmine.Matchers.Any = function(expectedClass) {
|
||||
this.expectedClass = expectedClass;
|
||||
};
|
||||
|
||||
jasmine.Matchers.Any.prototype.matches = function(other) {
|
||||
if (this.expectedClass == String) {
|
||||
return typeof other == 'string' || other instanceof String;
|
||||
}
|
||||
|
||||
if (this.expectedClass == Number) {
|
||||
return typeof other == 'number' || other instanceof Number;
|
||||
}
|
||||
|
||||
if (this.expectedClass == Function) {
|
||||
return typeof other == 'function' || other instanceof Function;
|
||||
}
|
||||
|
||||
if (this.expectedClass == Object) {
|
||||
return typeof other == 'object';
|
||||
}
|
||||
|
||||
return other instanceof this.expectedClass;
|
||||
};
|
||||
|
||||
jasmine.Matchers.Any.prototype.toString = function() {
|
||||
return '<jasmine.any(' + this.expectedClass + ')>';
|
||||
};
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
jasmine.MultiReporter = function() {
|
||||
this.subReporters_ = [];
|
||||
};
|
||||
jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
|
||||
|
||||
jasmine.MultiReporter.prototype.addReporter = function(reporter) {
|
||||
this.subReporters_.push(reporter);
|
||||
};
|
||||
|
||||
(function() {
|
||||
var functionNames = [
|
||||
"reportRunnerStarting",
|
||||
"reportRunnerResults",
|
||||
"reportSuiteResults",
|
||||
"reportSpecStarting",
|
||||
"reportSpecResults",
|
||||
"log"
|
||||
];
|
||||
for (var i = 0; i < functionNames.length; i++) {
|
||||
var functionName = functionNames[i];
|
||||
jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
|
||||
return function() {
|
||||
for (var j = 0; j < this.subReporters_.length; j++) {
|
||||
var subReporter = this.subReporters_[j];
|
||||
if (subReporter[functionName]) {
|
||||
subReporter[functionName].apply(subReporter, arguments);
|
||||
}
|
||||
}
|
||||
};
|
||||
})(functionName);
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
jasmine.NestedResults = function() {
|
||||
/**
|
||||
* The total count of results
|
||||
*/
|
||||
this.totalCount = 0;
|
||||
/**
|
||||
* Number of passed results
|
||||
*/
|
||||
this.passedCount = 0;
|
||||
/**
|
||||
* Number of failed results
|
||||
*/
|
||||
this.failedCount = 0;
|
||||
/**
|
||||
* Was this suite/spec skipped?
|
||||
*/
|
||||
this.skipped = false;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
this.items_ = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Roll up the result counts.
|
||||
*
|
||||
* @param result
|
||||
*/
|
||||
jasmine.NestedResults.prototype.rollupCounts = function(result) {
|
||||
this.totalCount += result.totalCount;
|
||||
this.passedCount += result.passedCount;
|
||||
this.failedCount += result.failedCount;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a log message.
|
||||
* @param values Array of message parts which will be concatenated later.
|
||||
*/
|
||||
jasmine.NestedResults.prototype.log = function(values) {
|
||||
this.items_.push(new jasmine.MessageResult(values));
|
||||
};
|
||||
|
||||
/**
|
||||
* Getter for the results: message & results.
|
||||
*/
|
||||
jasmine.NestedResults.prototype.getItems = function() {
|
||||
return this.items_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a result, tracking counts (total, passed, & failed)
|
||||
* @param {jasmine.ExpectationResult|jasmine.NestedResults} result
|
||||
*/
|
||||
jasmine.NestedResults.prototype.addResult = function(result) {
|
||||
if (result.type != 'log') {
|
||||
if (result.items_) {
|
||||
this.rollupCounts(result);
|
||||
} else {
|
||||
this.totalCount++;
|
||||
if (result.passed()) {
|
||||
this.passedCount++;
|
||||
} else {
|
||||
this.failedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.items_.push(result);
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {Boolean} True if <b>everything</b> below passed
|
||||
*/
|
||||
jasmine.NestedResults.prototype.passed = function() {
|
||||
return this.passedCount === this.totalCount;
|
||||
};
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Base class for pretty printing for expectation results.
|
||||
*/
|
||||
jasmine.PrettyPrinter = function() {
|
||||
this.ppNestLevel_ = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a value in a nice, human-readable string.
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
jasmine.PrettyPrinter.prototype.format = function(value) {
|
||||
if (this.ppNestLevel_ > 40) {
|
||||
throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
|
||||
}
|
||||
|
||||
this.ppNestLevel_++;
|
||||
try {
|
||||
if (value === jasmine.undefined) {
|
||||
this.emitScalar('undefined');
|
||||
} else if (value === null) {
|
||||
this.emitScalar('null');
|
||||
} else if (value === jasmine.getGlobal()) {
|
||||
this.emitScalar('<global>');
|
||||
} else if (value instanceof jasmine.Matchers.Any) {
|
||||
this.emitScalar(value.toString());
|
||||
} else if (typeof value === 'string') {
|
||||
this.emitString(value);
|
||||
} else if (jasmine.isSpy(value)) {
|
||||
this.emitScalar("spy on " + value.identity);
|
||||
} else if (value instanceof RegExp) {
|
||||
this.emitScalar(value.toString());
|
||||
} else if (typeof value === 'function') {
|
||||
this.emitScalar('Function');
|
||||
} else if (typeof value.nodeType === 'number') {
|
||||
this.emitScalar('HTMLNode');
|
||||
} else if (value instanceof Date) {
|
||||
this.emitScalar('Date(' + value + ')');
|
||||
} else if (value.__Jasmine_been_here_before__) {
|
||||
this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
|
||||
} else if (jasmine.isArray_(value) || typeof value == 'object') {
|
||||
value.__Jasmine_been_here_before__ = true;
|
||||
if (jasmine.isArray_(value)) {
|
||||
this.emitArray(value);
|
||||
} else {
|
||||
this.emitObject(value);
|
||||
}
|
||||
delete value.__Jasmine_been_here_before__;
|
||||
} else {
|
||||
this.emitScalar(value.toString());
|
||||
}
|
||||
} finally {
|
||||
this.ppNestLevel_--;
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
|
||||
for (var property in obj) {
|
||||
if (property == '__Jasmine_been_here_before__') continue;
|
||||
fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) != null) : false);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
|
||||
jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
|
||||
jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
|
||||
jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
|
||||
|
||||
jasmine.StringPrettyPrinter = function() {
|
||||
jasmine.PrettyPrinter.call(this);
|
||||
|
||||
this.string = '';
|
||||
};
|
||||
jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
|
||||
|
||||
jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
|
||||
this.append(value);
|
||||
};
|
||||
|
||||
jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
|
||||
this.append("'" + value + "'");
|
||||
};
|
||||
|
||||
jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
|
||||
this.append('[ ');
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
if (i > 0) {
|
||||
this.append(', ');
|
||||
}
|
||||
this.format(array[i]);
|
||||
}
|
||||
this.append(' ]');
|
||||
};
|
||||
|
||||
jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
|
||||
var self = this;
|
||||
this.append('{ ');
|
||||
var first = true;
|
||||
|
||||
this.iterateObject(obj, function(property, isGetter) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
self.append(', ');
|
||||
}
|
||||
|
||||
self.append(property);
|
||||
self.append(' : ');
|
||||
if (isGetter) {
|
||||
self.append('<getter>');
|
||||
} else {
|
||||
self.format(obj[property]);
|
||||
}
|
||||
});
|
||||
|
||||
this.append(' }');
|
||||
};
|
||||
|
||||
jasmine.StringPrettyPrinter.prototype.append = function(value) {
|
||||
this.string += value;
|
||||
};
|
||||
@@ -0,0 +1,99 @@
|
||||
jasmine.Queue = function(env) {
|
||||
this.env = env;
|
||||
this.blocks = [];
|
||||
this.running = false;
|
||||
this.index = 0;
|
||||
this.offset = 0;
|
||||
this.abort = false;
|
||||
};
|
||||
|
||||
jasmine.Queue.prototype.addBefore = function(block) {
|
||||
this.blocks.unshift(block);
|
||||
};
|
||||
|
||||
jasmine.Queue.prototype.add = function(block) {
|
||||
this.blocks.push(block);
|
||||
};
|
||||
|
||||
jasmine.Queue.prototype.insertNext = function(block) {
|
||||
this.blocks.splice((this.index + this.offset + 1), 0, block);
|
||||
this.offset++;
|
||||
};
|
||||
|
||||
jasmine.Queue.prototype.start = function(onComplete) {
|
||||
this.running = true;
|
||||
this.onComplete = onComplete;
|
||||
this.next_();
|
||||
};
|
||||
|
||||
jasmine.Queue.prototype.isRunning = function() {
|
||||
return this.running;
|
||||
};
|
||||
|
||||
jasmine.Queue.LOOP_DONT_RECURSE = true;
|
||||
|
||||
jasmine.Queue.prototype.next_ = function() {
|
||||
var self = this;
|
||||
var goAgain = true;
|
||||
|
||||
while (goAgain) {
|
||||
goAgain = false;
|
||||
|
||||
if (self.index < self.blocks.length && !this.abort) {
|
||||
var calledSynchronously = true;
|
||||
var completedSynchronously = false;
|
||||
|
||||
var onComplete = function () {
|
||||
if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
|
||||
completedSynchronously = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.blocks[self.index].abort) {
|
||||
self.abort = true;
|
||||
}
|
||||
|
||||
self.offset = 0;
|
||||
self.index++;
|
||||
|
||||
var now = new Date().getTime();
|
||||
if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
|
||||
self.env.lastUpdate = now;
|
||||
self.env.setTimeout(function() {
|
||||
self.next_();
|
||||
}, 0);
|
||||
} else {
|
||||
if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
|
||||
goAgain = true;
|
||||
} else {
|
||||
self.next_();
|
||||
}
|
||||
}
|
||||
};
|
||||
self.blocks[self.index].execute(onComplete);
|
||||
|
||||
calledSynchronously = false;
|
||||
if (completedSynchronously) {
|
||||
onComplete();
|
||||
}
|
||||
|
||||
} else {
|
||||
self.running = false;
|
||||
if (self.onComplete) {
|
||||
self.onComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.Queue.prototype.results = function() {
|
||||
var results = new jasmine.NestedResults();
|
||||
for (var i = 0; i < this.blocks.length; i++) {
|
||||
if (this.blocks[i].results) {
|
||||
results.addResult(this.blocks[i].results());
|
||||
}
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/** No-op base class for Jasmine reporters.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
jasmine.Reporter = function() {
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
jasmine.Reporter.prototype.reportSpecResults = function(spec) {
|
||||
};
|
||||
|
||||
//noinspection JSUnusedLocalSymbols
|
||||
jasmine.Reporter.prototype.log = function(str) {
|
||||
};
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Runner
|
||||
*
|
||||
* @constructor
|
||||
* @param {jasmine.Env} env
|
||||
*/
|
||||
jasmine.Runner = function(env) {
|
||||
var self = this;
|
||||
self.env = env;
|
||||
self.queue = new jasmine.Queue(env);
|
||||
self.before_ = [];
|
||||
self.after_ = [];
|
||||
self.suites_ = [];
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.execute = function() {
|
||||
var self = this;
|
||||
if (self.env.reporter.reportRunnerStarting) {
|
||||
self.env.reporter.reportRunnerStarting(this);
|
||||
}
|
||||
self.queue.start(function () {
|
||||
self.finishCallback();
|
||||
});
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
|
||||
beforeEachFunction.typeName = 'beforeEach';
|
||||
this.before_.splice(0,0,beforeEachFunction);
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
|
||||
afterEachFunction.typeName = 'afterEach';
|
||||
this.after_.splice(0,0,afterEachFunction);
|
||||
};
|
||||
|
||||
|
||||
jasmine.Runner.prototype.finishCallback = function() {
|
||||
this.env.reporter.reportRunnerResults(this);
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.addSuite = function(suite) {
|
||||
this.suites_.push(suite);
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.add = function(block) {
|
||||
if (block instanceof jasmine.Suite) {
|
||||
this.addSuite(block);
|
||||
}
|
||||
this.queue.add(block);
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.specs = function () {
|
||||
var suites = this.suites();
|
||||
var specs = [];
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
specs = specs.concat(suites[i].specs());
|
||||
}
|
||||
return specs;
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.suites = function() {
|
||||
return this.suites_;
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.topLevelSuites = function() {
|
||||
var topLevelSuites = [];
|
||||
for (var i = 0; i < this.suites_.length; i++) {
|
||||
if (!this.suites_[i].parentSuite) {
|
||||
topLevelSuites.push(this.suites_[i]);
|
||||
}
|
||||
}
|
||||
return topLevelSuites;
|
||||
};
|
||||
|
||||
jasmine.Runner.prototype.results = function() {
|
||||
return this.queue.results();
|
||||
};
|
||||
@@ -0,0 +1,242 @@
|
||||
/**
|
||||
* Internal representation of a Jasmine specification, or test.
|
||||
*
|
||||
* @constructor
|
||||
* @param {jasmine.Env} env
|
||||
* @param {jasmine.Suite} suite
|
||||
* @param {String} description
|
||||
*/
|
||||
jasmine.Spec = function(env, suite, description) {
|
||||
if (!env) {
|
||||
throw new Error('jasmine.Env() required');
|
||||
}
|
||||
if (!suite) {
|
||||
throw new Error('jasmine.Suite() required');
|
||||
}
|
||||
var spec = this;
|
||||
spec.id = env.nextSpecId ? env.nextSpecId() : null;
|
||||
spec.env = env;
|
||||
spec.suite = suite;
|
||||
spec.description = description;
|
||||
spec.queue = new jasmine.Queue(env);
|
||||
|
||||
spec.afterCallbacks = [];
|
||||
spec.spies_ = [];
|
||||
|
||||
spec.results_ = new jasmine.NestedResults();
|
||||
spec.results_.description = description;
|
||||
spec.matchersClass = null;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.getFullName = function() {
|
||||
return this.suite.getFullName() + ' ' + this.description + '.';
|
||||
};
|
||||
|
||||
|
||||
jasmine.Spec.prototype.results = function() {
|
||||
return this.results_;
|
||||
};
|
||||
|
||||
/**
|
||||
* All parameters are pretty-printed and concatenated together, then written to the spec's output.
|
||||
*
|
||||
* Be careful not to leave calls to <code>jasmine.log</code> in production code.
|
||||
*/
|
||||
jasmine.Spec.prototype.log = function() {
|
||||
return this.results_.log(arguments);
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.runs = function (func) {
|
||||
var block = new jasmine.Block(this.env, func, this);
|
||||
this.addToQueue(block);
|
||||
return this;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.addToQueue = function (block) {
|
||||
if (this.queue.isRunning()) {
|
||||
this.queue.insertNext(block);
|
||||
} else {
|
||||
this.queue.add(block);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {jasmine.ExpectationResult} result
|
||||
*/
|
||||
jasmine.Spec.prototype.addMatcherResult = function(result) {
|
||||
this.results_.addResult(result);
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.expect = function(actual) {
|
||||
var positive = new (this.getMatchersClass_())(this.env, actual, this);
|
||||
positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
|
||||
return positive;
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits a fixed time period before moving to the next block.
|
||||
*
|
||||
* @deprecated Use waitsFor() instead
|
||||
* @param {Number} timeout milliseconds to wait
|
||||
*/
|
||||
jasmine.Spec.prototype.waits = function(timeout) {
|
||||
var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
|
||||
this.addToQueue(waitsFunc);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits for the latchFunction to return true before proceeding to the next block.
|
||||
*
|
||||
* @param {Function} latchFunction
|
||||
* @param {String} optional_timeoutMessage
|
||||
* @param {Number} optional_timeout
|
||||
*/
|
||||
jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
|
||||
var latchFunction_ = null;
|
||||
var optional_timeoutMessage_ = null;
|
||||
var optional_timeout_ = null;
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var arg = arguments[i];
|
||||
switch (typeof arg) {
|
||||
case 'function':
|
||||
latchFunction_ = arg;
|
||||
break;
|
||||
case 'string':
|
||||
optional_timeoutMessage_ = arg;
|
||||
break;
|
||||
case 'number':
|
||||
optional_timeout_ = arg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
|
||||
this.addToQueue(waitsForFunc);
|
||||
return this;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.fail = function (e) {
|
||||
var expectationResult = new jasmine.ExpectationResult({
|
||||
passed: false,
|
||||
message: e ? jasmine.util.formatException(e) : 'Exception'
|
||||
});
|
||||
this.results_.addResult(expectationResult);
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.getMatchersClass_ = function() {
|
||||
return this.matchersClass || this.env.matchersClass;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
|
||||
var parent = this.getMatchersClass_();
|
||||
var newMatchersClass = function() {
|
||||
parent.apply(this, arguments);
|
||||
};
|
||||
jasmine.util.inherit(newMatchersClass, parent);
|
||||
jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
|
||||
this.matchersClass = newMatchersClass;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.finishCallback = function() {
|
||||
this.env.reporter.reportSpecResults(this);
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.finish = function(onComplete) {
|
||||
this.removeAllSpies();
|
||||
this.finishCallback();
|
||||
if (onComplete) {
|
||||
onComplete();
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.after = function(doAfter) {
|
||||
if (this.queue.isRunning()) {
|
||||
this.queue.add(new jasmine.Block(this.env, doAfter, this));
|
||||
} else {
|
||||
this.afterCallbacks.unshift(doAfter);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.execute = function(onComplete) {
|
||||
var spec = this;
|
||||
if (!spec.env.specFilter(spec)) {
|
||||
spec.results_.skipped = true;
|
||||
spec.finish(onComplete);
|
||||
return;
|
||||
}
|
||||
|
||||
this.env.reporter.reportSpecStarting(this);
|
||||
|
||||
spec.env.currentSpec = spec;
|
||||
|
||||
spec.addBeforesAndAftersToQueue();
|
||||
|
||||
spec.queue.start(function () {
|
||||
spec.finish(onComplete);
|
||||
});
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
|
||||
var runner = this.env.currentRunner();
|
||||
var i;
|
||||
|
||||
for (var suite = this.suite; suite; suite = suite.parentSuite) {
|
||||
for (i = 0; i < suite.before_.length; i++) {
|
||||
this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
|
||||
}
|
||||
}
|
||||
for (i = 0; i < runner.before_.length; i++) {
|
||||
this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
|
||||
}
|
||||
for (i = 0; i < this.afterCallbacks.length; i++) {
|
||||
this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
|
||||
}
|
||||
for (suite = this.suite; suite; suite = suite.parentSuite) {
|
||||
for (i = 0; i < suite.after_.length; i++) {
|
||||
this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
|
||||
}
|
||||
}
|
||||
for (i = 0; i < runner.after_.length; i++) {
|
||||
this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.explodes = function() {
|
||||
throw 'explodes function should not have been called';
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
|
||||
if (obj == jasmine.undefined) {
|
||||
throw "spyOn could not find an object to spy upon for " + methodName + "()";
|
||||
}
|
||||
|
||||
if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
|
||||
throw methodName + '() method does not exist';
|
||||
}
|
||||
|
||||
if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
|
||||
throw new Error(methodName + ' has already been spied upon');
|
||||
}
|
||||
|
||||
var spyObj = jasmine.createSpy(methodName);
|
||||
|
||||
this.spies_.push(spyObj);
|
||||
spyObj.baseObj = obj;
|
||||
spyObj.methodName = methodName;
|
||||
spyObj.originalValue = obj[methodName];
|
||||
|
||||
obj[methodName] = spyObj;
|
||||
|
||||
return spyObj;
|
||||
};
|
||||
|
||||
jasmine.Spec.prototype.removeAllSpies = function() {
|
||||
for (var i = 0; i < this.spies_.length; i++) {
|
||||
var spy = this.spies_[i];
|
||||
spy.baseObj[spy.methodName] = spy.originalValue;
|
||||
}
|
||||
this.spies_ = [];
|
||||
};
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Internal representation of a Jasmine suite.
|
||||
*
|
||||
* @constructor
|
||||
* @param {jasmine.Env} env
|
||||
* @param {String} description
|
||||
* @param {Function} specDefinitions
|
||||
* @param {jasmine.Suite} parentSuite
|
||||
*/
|
||||
jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
|
||||
var self = this;
|
||||
self.id = env.nextSuiteId ? env.nextSuiteId() : null;
|
||||
self.description = description;
|
||||
self.queue = new jasmine.Queue(env);
|
||||
self.parentSuite = parentSuite;
|
||||
self.env = env;
|
||||
self.before_ = [];
|
||||
self.after_ = [];
|
||||
self.children_ = [];
|
||||
self.suites_ = [];
|
||||
self.specs_ = [];
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.getFullName = function() {
|
||||
var fullName = this.description;
|
||||
for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
|
||||
fullName = parentSuite.description + ' ' + fullName;
|
||||
}
|
||||
return fullName;
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.finish = function(onComplete) {
|
||||
this.env.reporter.reportSuiteResults(this);
|
||||
this.finished = true;
|
||||
if (typeof(onComplete) == 'function') {
|
||||
onComplete();
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
|
||||
beforeEachFunction.typeName = 'beforeEach';
|
||||
this.before_.unshift(beforeEachFunction);
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
|
||||
afterEachFunction.typeName = 'afterEach';
|
||||
this.after_.unshift(afterEachFunction);
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.results = function() {
|
||||
return this.queue.results();
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.add = function(suiteOrSpec) {
|
||||
this.children_.push(suiteOrSpec);
|
||||
if (suiteOrSpec instanceof jasmine.Suite) {
|
||||
this.suites_.push(suiteOrSpec);
|
||||
this.env.currentRunner().addSuite(suiteOrSpec);
|
||||
} else {
|
||||
this.specs_.push(suiteOrSpec);
|
||||
}
|
||||
this.queue.add(suiteOrSpec);
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.specs = function() {
|
||||
return this.specs_;
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.suites = function() {
|
||||
return this.suites_;
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.children = function() {
|
||||
return this.children_;
|
||||
};
|
||||
|
||||
jasmine.Suite.prototype.execute = function(onComplete) {
|
||||
var self = this;
|
||||
this.queue.start(function () {
|
||||
self.finish(onComplete);
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
jasmine.WaitsBlock = function(env, timeout, spec) {
|
||||
this.timeout = timeout;
|
||||
jasmine.Block.call(this, env, null, spec);
|
||||
};
|
||||
|
||||
jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
|
||||
|
||||
jasmine.WaitsBlock.prototype.execute = function (onComplete) {
|
||||
this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
|
||||
this.env.setTimeout(function () {
|
||||
onComplete();
|
||||
}, this.timeout);
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* A block which waits for some condition to become true, with timeout.
|
||||
*
|
||||
* @constructor
|
||||
* @extends jasmine.Block
|
||||
* @param {jasmine.Env} env The Jasmine environment.
|
||||
* @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
|
||||
* @param {Function} latchFunction A function which returns true when the desired condition has been met.
|
||||
* @param {String} message The message to display if the desired condition hasn't been met within the given time period.
|
||||
* @param {jasmine.Spec} spec The Jasmine spec.
|
||||
*/
|
||||
jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
|
||||
this.timeout = timeout || env.defaultTimeoutInterval;
|
||||
this.latchFunction = latchFunction;
|
||||
this.message = message;
|
||||
this.totalTimeSpentWaitingForLatch = 0;
|
||||
jasmine.Block.call(this, env, null, spec);
|
||||
};
|
||||
jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
|
||||
|
||||
jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
|
||||
|
||||
jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
|
||||
this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
|
||||
var latchFunctionResult;
|
||||
try {
|
||||
latchFunctionResult = this.latchFunction.apply(this.spec);
|
||||
} catch (e) {
|
||||
this.spec.fail(e);
|
||||
onComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
if (latchFunctionResult) {
|
||||
onComplete();
|
||||
} else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
|
||||
var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
|
||||
this.spec.fail({
|
||||
name: 'timeout',
|
||||
message: message
|
||||
});
|
||||
|
||||
this.abort = true;
|
||||
onComplete();
|
||||
} else {
|
||||
this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
|
||||
var self = this;
|
||||
this.env.setTimeout(function() {
|
||||
self.execute(onComplete);
|
||||
}, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,589 @@
|
||||
/**
|
||||
* Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var jasmine = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
jasmine.unimplementedMethod_ = function() {
|
||||
throw new Error("unimplemented method");
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
jasmine.undefined = jasmine.___undefined___;
|
||||
|
||||
/**
|
||||
* Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
|
||||
*
|
||||
*/
|
||||
jasmine.DEFAULT_UPDATE_INTERVAL = 250;
|
||||
|
||||
/**
|
||||
* Default timeout interval in milliseconds for waitsFor() blocks.
|
||||
*/
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
|
||||
|
||||
jasmine.getGlobal = function() {
|
||||
function getGlobal() {
|
||||
return this;
|
||||
}
|
||||
|
||||
return getGlobal();
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows for bound functions to be compared. Internal use only.
|
||||
*
|
||||
* @ignore
|
||||
* @private
|
||||
* @param base {Object} bound 'this' for the function
|
||||
* @param name {Function} function to find
|
||||
*/
|
||||
jasmine.bindOriginal_ = function(base, name) {
|
||||
var original = base[name];
|
||||
if (original.apply) {
|
||||
return function() {
|
||||
return original.apply(base, arguments);
|
||||
};
|
||||
} else {
|
||||
// IE support
|
||||
return jasmine.getGlobal()[name];
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
|
||||
jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
|
||||
jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
|
||||
jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
|
||||
|
||||
jasmine.MessageResult = function(values) {
|
||||
this.type = 'log';
|
||||
this.values = values;
|
||||
this.trace = new Error(); // todo: test better
|
||||
};
|
||||
|
||||
jasmine.MessageResult.prototype.toString = function() {
|
||||
var text = "";
|
||||
for(var i = 0; i < this.values.length; i++) {
|
||||
if (i > 0) text += " ";
|
||||
if (jasmine.isString_(this.values[i])) {
|
||||
text += this.values[i];
|
||||
} else {
|
||||
text += jasmine.pp(this.values[i]);
|
||||
}
|
||||
}
|
||||
return text;
|
||||
};
|
||||
|
||||
jasmine.ExpectationResult = function(params) {
|
||||
this.type = 'expect';
|
||||
this.matcherName = params.matcherName;
|
||||
this.passed_ = params.passed;
|
||||
this.expected = params.expected;
|
||||
this.actual = params.actual;
|
||||
|
||||
this.message = this.passed_ ? 'Passed.' : params.message;
|
||||
this.trace = this.passed_ ? '' : new Error(this.message);
|
||||
};
|
||||
|
||||
jasmine.ExpectationResult.prototype.toString = function () {
|
||||
return this.message;
|
||||
};
|
||||
|
||||
jasmine.ExpectationResult.prototype.passed = function () {
|
||||
return this.passed_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Getter for the Jasmine environment. Ensures one gets created
|
||||
*/
|
||||
jasmine.getEnv = function() {
|
||||
return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
|
||||
};
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* @private
|
||||
* @param value
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
jasmine.isArray_ = function(value) {
|
||||
return jasmine.isA_("Array", value);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* @private
|
||||
* @param value
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
jasmine.isString_ = function(value) {
|
||||
return jasmine.isA_("String", value);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* @private
|
||||
* @param value
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
jasmine.isNumber_ = function(value) {
|
||||
return jasmine.isA_("Number", value);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* @private
|
||||
* @param {String} typeName
|
||||
* @param value
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
jasmine.isA_ = function(typeName, value) {
|
||||
return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
|
||||
};
|
||||
|
||||
/**
|
||||
* Pretty printer for expecations. Takes any object and turns it into a human-readable string.
|
||||
*
|
||||
* @param value {Object} an object to be outputted
|
||||
* @returns {String}
|
||||
*/
|
||||
jasmine.pp = function(value) {
|
||||
var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
|
||||
stringPrettyPrinter.format(value);
|
||||
return stringPrettyPrinter.string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the object is a DOM Node.
|
||||
*
|
||||
* @param {Object} obj object to check
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
jasmine.isDomNode = function(obj) {
|
||||
return obj['nodeType'] > 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter.
|
||||
*
|
||||
* @example
|
||||
* // don't care about which function is passed in, as long as it's a function
|
||||
* expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
*
|
||||
* @param {Class} clazz
|
||||
* @returns matchable object of the type clazz
|
||||
*/
|
||||
jasmine.any = function(clazz) {
|
||||
return new jasmine.Matchers.Any(clazz);
|
||||
};
|
||||
|
||||
/**
|
||||
* Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
|
||||
*
|
||||
* Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine
|
||||
* expectation syntax. Spies can be checked if they were called or not and what the calling params were.
|
||||
*
|
||||
* A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
|
||||
*
|
||||
* Spies are torn down at the end of every spec.
|
||||
*
|
||||
* Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
|
||||
*
|
||||
* @example
|
||||
* // a stub
|
||||
* var myStub = jasmine.createSpy('myStub'); // can be used anywhere
|
||||
*
|
||||
* // spy example
|
||||
* var foo = {
|
||||
* not: function(bool) { return !bool; }
|
||||
* }
|
||||
*
|
||||
* // actual foo.not will not be called, execution stops
|
||||
* spyOn(foo, 'not');
|
||||
|
||||
// foo.not spied upon, execution will continue to implementation
|
||||
* spyOn(foo, 'not').andCallThrough();
|
||||
*
|
||||
* // fake example
|
||||
* var foo = {
|
||||
* not: function(bool) { return !bool; }
|
||||
* }
|
||||
*
|
||||
* // foo.not(val) will return val
|
||||
* spyOn(foo, 'not').andCallFake(function(value) {return value;});
|
||||
*
|
||||
* // mock example
|
||||
* foo.not(7 == 7);
|
||||
* expect(foo.not).toHaveBeenCalled();
|
||||
* expect(foo.not).toHaveBeenCalledWith(true);
|
||||
*
|
||||
* @constructor
|
||||
* @see spyOn, jasmine.createSpy, jasmine.createSpyObj
|
||||
* @param {String} name
|
||||
*/
|
||||
jasmine.Spy = function(name) {
|
||||
/**
|
||||
* The name of the spy, if provided.
|
||||
*/
|
||||
this.identity = name || 'unknown';
|
||||
/**
|
||||
* Is this Object a spy?
|
||||
*/
|
||||
this.isSpy = true;
|
||||
/**
|
||||
* The actual function this spy stubs.
|
||||
*/
|
||||
this.plan = function() {
|
||||
};
|
||||
/**
|
||||
* Tracking of the most recent call to the spy.
|
||||
* @example
|
||||
* var mySpy = jasmine.createSpy('foo');
|
||||
* mySpy(1, 2);
|
||||
* mySpy.mostRecentCall.args = [1, 2];
|
||||
*/
|
||||
this.mostRecentCall = {};
|
||||
|
||||
/**
|
||||
* Holds arguments for each call to the spy, indexed by call count
|
||||
* @example
|
||||
* var mySpy = jasmine.createSpy('foo');
|
||||
* mySpy(1, 2);
|
||||
* mySpy(7, 8);
|
||||
* mySpy.mostRecentCall.args = [7, 8];
|
||||
* mySpy.argsForCall[0] = [1, 2];
|
||||
* mySpy.argsForCall[1] = [7, 8];
|
||||
*/
|
||||
this.argsForCall = [];
|
||||
this.calls = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Tells a spy to call through to the actual implemenatation.
|
||||
*
|
||||
* @example
|
||||
* var foo = {
|
||||
* bar: function() { // do some stuff }
|
||||
* }
|
||||
*
|
||||
* // defining a spy on an existing property: foo.bar
|
||||
* spyOn(foo, 'bar').andCallThrough();
|
||||
*/
|
||||
jasmine.Spy.prototype.andCallThrough = function() {
|
||||
this.plan = this.originalValue;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* For setting the return value of a spy.
|
||||
*
|
||||
* @example
|
||||
* // defining a spy from scratch: foo() returns 'baz'
|
||||
* var foo = jasmine.createSpy('spy on foo').andReturn('baz');
|
||||
*
|
||||
* // defining a spy on an existing property: foo.bar() returns 'baz'
|
||||
* spyOn(foo, 'bar').andReturn('baz');
|
||||
*
|
||||
* @param {Object} value
|
||||
*/
|
||||
jasmine.Spy.prototype.andReturn = function(value) {
|
||||
this.plan = function() {
|
||||
return value;
|
||||
};
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* For throwing an exception when a spy is called.
|
||||
*
|
||||
* @example
|
||||
* // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
|
||||
* var foo = jasmine.createSpy('spy on foo').andThrow('baz');
|
||||
*
|
||||
* // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
|
||||
* spyOn(foo, 'bar').andThrow('baz');
|
||||
*
|
||||
* @param {String} exceptionMsg
|
||||
*/
|
||||
jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
|
||||
this.plan = function() {
|
||||
throw exceptionMsg;
|
||||
};
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls an alternate implementation when a spy is called.
|
||||
*
|
||||
* @example
|
||||
* var baz = function() {
|
||||
* // do some stuff, return something
|
||||
* }
|
||||
* // defining a spy from scratch: foo() calls the function baz
|
||||
* var foo = jasmine.createSpy('spy on foo').andCall(baz);
|
||||
*
|
||||
* // defining a spy on an existing property: foo.bar() calls an anonymnous function
|
||||
* spyOn(foo, 'bar').andCall(function() { return 'baz';} );
|
||||
*
|
||||
* @param {Function} fakeFunc
|
||||
*/
|
||||
jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
|
||||
this.plan = fakeFunc;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resets all of a spy's the tracking variables so that it can be used again.
|
||||
*
|
||||
* @example
|
||||
* spyOn(foo, 'bar');
|
||||
*
|
||||
* foo.bar();
|
||||
*
|
||||
* expect(foo.bar.callCount).toEqual(1);
|
||||
*
|
||||
* foo.bar.reset();
|
||||
*
|
||||
* expect(foo.bar.callCount).toEqual(0);
|
||||
*/
|
||||
jasmine.Spy.prototype.reset = function() {
|
||||
this.wasCalled = false;
|
||||
this.callCount = 0;
|
||||
this.argsForCall = [];
|
||||
this.calls = [];
|
||||
this.mostRecentCall = {};
|
||||
};
|
||||
|
||||
jasmine.createSpy = function(name) {
|
||||
|
||||
var spyObj = function() {
|
||||
spyObj.wasCalled = true;
|
||||
spyObj.callCount++;
|
||||
var args = jasmine.util.argsToArray(arguments);
|
||||
spyObj.mostRecentCall.object = this;
|
||||
spyObj.mostRecentCall.args = args;
|
||||
spyObj.argsForCall.push(args);
|
||||
spyObj.calls.push({object: this, args: args});
|
||||
return spyObj.plan.apply(this, arguments);
|
||||
};
|
||||
|
||||
var spy = new jasmine.Spy(name);
|
||||
|
||||
for (var prop in spy) {
|
||||
spyObj[prop] = spy[prop];
|
||||
}
|
||||
|
||||
spyObj.reset();
|
||||
|
||||
return spyObj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether an object is a spy.
|
||||
*
|
||||
* @param {jasmine.Spy|Object} putativeSpy
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
jasmine.isSpy = function(putativeSpy) {
|
||||
return putativeSpy && putativeSpy.isSpy;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something
|
||||
* large in one call.
|
||||
*
|
||||
* @param {String} baseName name of spy class
|
||||
* @param {Array} methodNames array of names of methods to make spies
|
||||
*/
|
||||
jasmine.createSpyObj = function(baseName, methodNames) {
|
||||
if (!jasmine.isArray_(methodNames) || methodNames.length == 0) {
|
||||
throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
|
||||
}
|
||||
var obj = {};
|
||||
for (var i = 0; i < methodNames.length; i++) {
|
||||
obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* All parameters are pretty-printed and concatenated together, then written to the current spec's output.
|
||||
*
|
||||
* Be careful not to leave calls to <code>jasmine.log</code> in production code.
|
||||
*/
|
||||
jasmine.log = function() {
|
||||
var spec = jasmine.getEnv().currentSpec;
|
||||
spec.log.apply(spec, arguments);
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that installs a spy on an existing object's method name. Used within a Spec to create a spy.
|
||||
*
|
||||
* @example
|
||||
* // spy example
|
||||
* var foo = {
|
||||
* not: function(bool) { return !bool; }
|
||||
* }
|
||||
* spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
|
||||
*
|
||||
* @see jasmine.createSpy
|
||||
* @param obj
|
||||
* @param methodName
|
||||
* @returns a Jasmine spy that can be chained with all spy methods
|
||||
*/
|
||||
var spyOn = function(obj, methodName) {
|
||||
return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a Jasmine spec that will be added to the current suite.
|
||||
*
|
||||
* // TODO: pending tests
|
||||
*
|
||||
* @example
|
||||
* it('should be true', function() {
|
||||
* expect(true).toEqual(true);
|
||||
* });
|
||||
*
|
||||
* @param {String} desc description of this specification
|
||||
* @param {Function} func defines the preconditions and expectations of the spec
|
||||
*/
|
||||
var it = function(desc, func) {
|
||||
return jasmine.getEnv().it(desc, func);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a <em>disabled</em> Jasmine spec.
|
||||
*
|
||||
* A convenience method that allows existing specs to be disabled temporarily during development.
|
||||
*
|
||||
* @param {String} desc description of this specification
|
||||
* @param {Function} func defines the preconditions and expectations of the spec
|
||||
*/
|
||||
var xit = function(desc, func) {
|
||||
return jasmine.getEnv().xit(desc, func);
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts a chain for a Jasmine expectation.
|
||||
*
|
||||
* It is passed an Object that is the actual value and should chain to one of the many
|
||||
* jasmine.Matchers functions.
|
||||
*
|
||||
* @param {Object} actual Actual value to test against and expected value
|
||||
*/
|
||||
var expect = function(actual) {
|
||||
return jasmine.getEnv().currentSpec.expect(actual);
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
|
||||
*
|
||||
* @param {Function} func Function that defines part of a jasmine spec.
|
||||
*/
|
||||
var runs = function(func) {
|
||||
jasmine.getEnv().currentSpec.runs(func);
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits a fixed time period before moving to the next block.
|
||||
*
|
||||
* @deprecated Use waitsFor() instead
|
||||
* @param {Number} timeout milliseconds to wait
|
||||
*/
|
||||
var waits = function(timeout) {
|
||||
jasmine.getEnv().currentSpec.waits(timeout);
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits for the latchFunction to return true before proceeding to the next block.
|
||||
*
|
||||
* @param {Function} latchFunction
|
||||
* @param {String} optional_timeoutMessage
|
||||
* @param {Number} optional_timeout
|
||||
*/
|
||||
var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
|
||||
jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
|
||||
};
|
||||
|
||||
/**
|
||||
* A function that is called before each spec in a suite.
|
||||
*
|
||||
* Used for spec setup, including validating assumptions.
|
||||
*
|
||||
* @param {Function} beforeEachFunction
|
||||
*/
|
||||
var beforeEach = function(beforeEachFunction) {
|
||||
jasmine.getEnv().beforeEach(beforeEachFunction);
|
||||
};
|
||||
|
||||
/**
|
||||
* A function that is called after each spec in a suite.
|
||||
*
|
||||
* Used for restoring any state that is hijacked during spec execution.
|
||||
*
|
||||
* @param {Function} afterEachFunction
|
||||
*/
|
||||
var afterEach = function(afterEachFunction) {
|
||||
jasmine.getEnv().afterEach(afterEachFunction);
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines a suite of specifications.
|
||||
*
|
||||
* Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
|
||||
* are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
|
||||
* of setup in some tests.
|
||||
*
|
||||
* @example
|
||||
* // TODO: a simple suite
|
||||
*
|
||||
* // TODO: a simple suite with a nested describe block
|
||||
*
|
||||
* @param {String} description A string, usually the class under test.
|
||||
* @param {Function} specDefinitions function that defines several specs.
|
||||
*/
|
||||
var describe = function(description, specDefinitions) {
|
||||
return jasmine.getEnv().describe(description, specDefinitions);
|
||||
};
|
||||
|
||||
/**
|
||||
* Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
|
||||
*
|
||||
* @param {String} description A string, usually the class under test.
|
||||
* @param {Function} specDefinitions function that defines several specs.
|
||||
*/
|
||||
var xdescribe = function(description, specDefinitions) {
|
||||
return jasmine.getEnv().xdescribe(description, specDefinitions);
|
||||
};
|
||||
|
||||
|
||||
// Provide the XMLHttpRequest class for IE 5.x-6.x:
|
||||
jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
|
||||
try {
|
||||
return new ActiveXObject("Msxml2.XMLHTTP.6.0");
|
||||
} catch(e) {
|
||||
}
|
||||
try {
|
||||
return new ActiveXObject("Msxml2.XMLHTTP.3.0");
|
||||
} catch(e) {
|
||||
}
|
||||
try {
|
||||
return new ActiveXObject("Msxml2.XMLHTTP");
|
||||
} catch(e) {
|
||||
}
|
||||
try {
|
||||
return new ActiveXObject("Microsoft.XMLHTTP");
|
||||
} catch(e) {
|
||||
}
|
||||
throw new Error("This browser does not support XMLHttpRequest.");
|
||||
} : XMLHttpRequest;
|
||||
@@ -0,0 +1,182 @@
|
||||
jasmine.TrivialReporter = function(doc) {
|
||||
this.document = doc || document;
|
||||
this.suiteDivs = {};
|
||||
this.logRunningSpecs = false;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
|
||||
var el = document.createElement(type);
|
||||
|
||||
for (var i = 2; i < arguments.length; i++) {
|
||||
var child = arguments[i];
|
||||
|
||||
if (typeof child === 'string') {
|
||||
el.appendChild(document.createTextNode(child));
|
||||
} else {
|
||||
if (child) { el.appendChild(child); }
|
||||
}
|
||||
}
|
||||
|
||||
for (var attr in attrs) {
|
||||
if (attr == "className") {
|
||||
el[attr] = attrs[attr];
|
||||
} else {
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
||||
var showPassed, showSkipped;
|
||||
|
||||
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
|
||||
this.createDom('div', { className: 'banner' },
|
||||
this.createDom('div', { className: 'logo' },
|
||||
this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "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);
|
||||
|
||||
var suites = runner.suites();
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
var suite = suites[i];
|
||||
var suiteDiv = this.createDom('div', { className: 'suite' },
|
||||
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.id] = suiteDiv;
|
||||
var parentDiv = this.outerDiv;
|
||||
if (suite.parentSuite) {
|
||||
parentDiv = this.suiteDivs[suite.parentSuite.id];
|
||||
}
|
||||
parentDiv.appendChild(suiteDiv);
|
||||
}
|
||||
|
||||
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) {
|
||||
var results = runner.results();
|
||||
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
|
||||
this.runnerDiv.setAttribute("class", className);
|
||||
//do it twice for IE
|
||||
this.runnerDiv.setAttribute("className", className);
|
||||
var specs = runner.specs();
|
||||
var specCount = 0;
|
||||
for (var i = 0; i < specs.length; i++) {
|
||||
if (this.specFilter(specs[i])) {
|
||||
specCount++;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
var results = suite.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.totalCount == 0) { // todo: change this to check results.skipped
|
||||
status = 'skipped';
|
||||
}
|
||||
this.suiteDivs[suite.id].className += " " + status;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
|
||||
if (this.logRunningSpecs) {
|
||||
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
|
||||
var results = spec.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.skipped) {
|
||||
status = 'skipped';
|
||||
}
|
||||
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()),
|
||||
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.type == 'log') {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||
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.id].appendChild(specDiv);
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.log = function() {
|
||||
var console = jasmine.getGlobal().console;
|
||||
if (console && console.log) console.log.apply(console, arguments);
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.getLocation = function() {
|
||||
return this.document.location;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
|
||||
var paramMap = {};
|
||||
var params = this.getLocation().search.substring(1).split('&');
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var p = params[i].split('=');
|
||||
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
||||
}
|
||||
|
||||
if (!paramMap["spec"]) return true;
|
||||
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
|
||||
};
|
||||
@@ -0,0 +1,166 @@
|
||||
body {
|
||||
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
|
||||
}
|
||||
|
||||
|
||||
.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 {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
|
||||
.options {
|
||||
text-align: right;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.suite {
|
||||
border: 1px outset gray;
|
||||
margin: 5px 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.suite .suite {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.suite.passed {
|
||||
background-color: #dfd;
|
||||
}
|
||||
|
||||
.suite.failed {
|
||||
background-color: #fdd;
|
||||
}
|
||||
|
||||
.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: #fbb;
|
||||
}
|
||||
|
||||
.skipped {
|
||||
color: #777;
|
||||
background-color: #eee;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*.resultMessage {*/
|
||||
/*white-space: pre;*/
|
||||
/*}*/
|
||||
|
||||
.resultMessage span.result {
|
||||
display: block;
|
||||
line-height: 2em;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.resultMessage .mismatch {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.stackTrace {
|
||||
white-space: pre;
|
||||
font-size: .8em;
|
||||
margin-left: 10px;
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
// 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() {
|
||||
if (!jasmine.Clock.isInstalled()) {
|
||||
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: jasmine.getGlobal().setTimeout,
|
||||
clearTimeout: jasmine.getGlobal().clearTimeout,
|
||||
setInterval: jasmine.getGlobal().setInterval,
|
||||
clearInterval: jasmine.getGlobal().clearInterval
|
||||
},
|
||||
|
||||
assertInstalled: function() {
|
||||
if (!jasmine.Clock.isInstalled()) {
|
||||
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
|
||||
}
|
||||
},
|
||||
|
||||
isInstalled: function() {
|
||||
return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
|
||||
},
|
||||
|
||||
installed: null
|
||||
};
|
||||
jasmine.Clock.installed = jasmine.Clock.real;
|
||||
|
||||
//else for IE support
|
||||
jasmine.getGlobal().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);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.getGlobal().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);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.getGlobal().clearTimeout = function(timeoutKey) {
|
||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
||||
return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.clearTimeout(timeoutKey);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.getGlobal().clearInterval = function(timeoutKey) {
|
||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
||||
return jasmine.Clock.installed.clearInterval.apply(this, arguments);
|
||||
} else {
|
||||
return jasmine.Clock.installed.clearInterval(timeoutKey);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @namespace
|
||||
*/
|
||||
jasmine.util = {};
|
||||
|
||||
/**
|
||||
* Declare that a child class inherit it's prototype from the parent class.
|
||||
*
|
||||
* @private
|
||||
* @param {Function} childClass
|
||||
* @param {Function} parentClass
|
||||
*/
|
||||
jasmine.util.inherit = function(childClass, parentClass) {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
var subclass = function() {
|
||||
};
|
||||
subclass.prototype = parentClass.prototype;
|
||||
childClass.prototype = new subclass;
|
||||
};
|
||||
|
||||
jasmine.util.formatException = function(e) {
|
||||
var lineNumber;
|
||||
if (e.line) {
|
||||
lineNumber = e.line;
|
||||
}
|
||||
else if (e.lineNumber) {
|
||||
lineNumber = e.lineNumber;
|
||||
}
|
||||
|
||||
var file;
|
||||
|
||||
if (e.sourceURL) {
|
||||
file = e.sourceURL;
|
||||
}
|
||||
else if (e.fileName) {
|
||||
file = e.fileName;
|
||||
}
|
||||
|
||||
var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
|
||||
|
||||
if (file && lineNumber) {
|
||||
message += ' in ' + file + ' (line ' + lineNumber + ')';
|
||||
}
|
||||
|
||||
return message;
|
||||
};
|
||||
|
||||
jasmine.util.htmlEscape = function(str) {
|
||||
if (!str) return str;
|
||||
return str.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
};
|
||||
|
||||
jasmine.util.argsToArray = function(args) {
|
||||
var arrayOfArgs = [];
|
||||
for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
|
||||
return arrayOfArgs;
|
||||
};
|
||||
|
||||
jasmine.util.extend = function(destination, source) {
|
||||
for (var property in source) destination[property] = source[property];
|
||||
return destination;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"major": 1,
|
||||
"minor": 0,
|
||||
"build": 0
|
||||
}
|
||||