diff --git a/README.markdown b/README.markdown index 14b4fff..006c239 100644 --- a/README.markdown +++ b/README.markdown @@ -6,7 +6,7 @@ Quick Start ---------- 1. Get the latest release from the [downloads page](http://github.com/pivotal/jasmine/downloads). -2. Open `example/example_runner.html` in your favorite browser. +2. Open `SpecRunner.html` in your favorite browser. For running within a Ruby environment, including automated execution with Selenium, please use the [jasmine gem](http://github.com/pivotal/jasmine-gem). diff --git a/Rakefile b/Rakefile index d55b53e..0bf7255 100644 --- a/Rakefile +++ b/Rakefile @@ -2,16 +2,21 @@ require File.expand_path(File.join(File.dirname(__FILE__), "spec/jasmine_helper. 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 += Dir.glob('src/*.js').reject { |f| f == 'src/base.js' || sources.include?(f) }.sort sources end -def jasmine_filename(version) - "jasmine-#{version['major']}.#{version['minor']}.#{version['build']}.js" +def jasmine_filename + "jasmine-#{jasmine_version}.js" +end + +def jasmine_version + "#{version_hash['major']}.#{version_hash['minor']}.#{version_hash['build']}" end def version_hash - JSON.parse(File.new("src/version.json").read); + require 'json' + @version ||= JSON.parse(File.new("src/version.json").read); end def start_jasmine_server(jasmine_includes = nil) @@ -21,18 +26,24 @@ def start_jasmine_server(jasmine_includes = nil) puts " http://localhost:8888/run.html" Jasmine::SimpleServer.start( - 8888, - lambda { JasmineHelper.specs }, - JasmineHelper.dir_mappings, - :jasmine_files => jasmine_includes) + 8888, + lambda { JasmineHelper.specs }, + JasmineHelper.dir_mappings, + :jasmine_files => jasmine_includes) end task :default => 'jasmine:dist' +def substitute_jasmine_version(filename) + contents = File.read(filename) + contents = contents.gsub(/##JASMINE_VERSION##/, (jasmine_version)) + File.open(filename, 'w') { |f| f.write(contents) } +end + namespace :jasmine do desc 'Prepares for distribution' - task :dist => ['jasmine:build', 'jasmine:doc'] + task :dist => ['jasmine:build', 'jasmine:doc', 'jasmine:build_example_project'] desc 'Check jasmine sources for coding problems' task :lint do @@ -63,7 +74,6 @@ namespace :jasmine do desc 'Builds lib/jasmine from source' task :build => :lint do puts 'Building Jasmine from source' - require 'json' sources = jasmine_sources version = version_hash @@ -106,12 +116,41 @@ jasmine.version_= { Rake::Task[:lambda_jsdoc].invoke end + desc "Build example project" + task :build_example_project 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 = JasmineHelper.jasmine_root + 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) + [ + "jasmine.js", + "TrivialReporter.js", + "jasmine.css" + ].each do |f| + FileUtils.cp(File.join(root, 'lib', f), File.join(lib_dir, f)) + end + + dist = File.join(root, 'dist') + FileUtils.rm_r dist if File.exists?(dist) + Dir.mkdir(dist) + exec "cd #{temp_dir} && zip -r #{File.join(dist, "jasmine-standalone-#{jasmine_version}.zip")} ." + end + task :server do files = jasmine_sources + ['lib/TrivialReporter.js', 'lib/consolex.js'] jasmine_includes = lambda { raw_jasmine_includes = files.collect { |f| File.expand_path(File.join(JasmineHelper.jasmine_root, f)) } - Jasmine.cachebust(raw_jasmine_includes).collect {|f| f.sub(JasmineHelper.jasmine_src_dir, "/src").sub(JasmineHelper.jasmine_lib_dir, "/lib") } + Jasmine.cachebust(raw_jasmine_includes).collect { |f| f.sub(JasmineHelper.jasmine_src_dir, "/src").sub(JasmineHelper.jasmine_lib_dir, "/lib") } } start_jasmine_server(jasmine_includes) end diff --git a/example/SpecRunner.html b/example/SpecRunner.html new file mode 100644 index 0000000..3f7f0e5 --- /dev/null +++ b/example/SpecRunner.html @@ -0,0 +1,27 @@ + + + + Jasmine Test Runner + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/example_runner.html b/example/example_runner.html deleted file mode 100644 index 5de3aea..0000000 --- a/example/example_runner.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - Jasmine Test Runner - - - - - - - - - - - - - diff --git a/example/spec/PlayerSpec.js b/example/spec/PlayerSpec.js new file mode 100644 index 0000000..79f1022 --- /dev/null +++ b/example/spec/PlayerSpec.js @@ -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"); + }); + }); +}); \ No newline at end of file diff --git a/example/spec/SpecHelper.js b/example/spec/SpecHelper.js new file mode 100644 index 0000000..4919c87 --- /dev/null +++ b/example/spec/SpecHelper.js @@ -0,0 +1,9 @@ +beforeEach(function() { + this.addMatchers({ + toBePlaying: function(expectedSong) { + var player = this.actual; + return player.currentlyPlayingSong === expectedSong + && player.isPlaying; + } + }) +}); diff --git a/example/spec/example_suite.js b/example/spec/example_suite.js deleted file mode 100644 index 494539e..0000000 --- a/example/spec/example_suite.js +++ /dev/null @@ -1,11 +0,0 @@ -describe('ExampleSuite', function () { - it('should have a passing test', function() { - expect(true).toEqual(true); - }); - - describe('Nested Describe', function () { - it('should also have a passing test', function () { - expect(true).toEqual(true); - }); - }); -}); \ No newline at end of file diff --git a/example/src/Player.js b/example/src/Player.js new file mode 100644 index 0000000..fcce826 --- /dev/null +++ b/example/src/Player.js @@ -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); +}; \ No newline at end of file diff --git a/example/src/Song.js b/example/src/Song.js new file mode 100644 index 0000000..a8a3f2d --- /dev/null +++ b/example/src/Song.js @@ -0,0 +1,7 @@ +function Song() { +} + +Song.prototype.persistFavoriteStatus = function(value) { + // something complicated + throw new Error("not yet implemented"); +}; \ No newline at end of file