From e53b4870171ec272d08d2fe6e99c4aec224889c5 Mon Sep 17 00:00:00 2001 From: Christopher Amavisca and Davis W Frank Date: Thu, 20 Mar 2014 16:12:44 -0700 Subject: [PATCH] - Add a main entry point for the jasmine-core npm - jasmine-core can now self test with the jasmine-npm - Add node examples files - Add node_boot.js for node environment - Move jasmine-core npm packaging to .npmignore - removing src_dir and src_files from jasmine.json b/c jasmine-npm does not support requiring source files automatically. --- .npmignore | 23 +++ Gruntfile.js | 17 +- grunt/config/concat.js | 4 + grunt/tasks/spec.js | 11 -- lib/jasmine-core.js | 2 + lib/jasmine-core.rb | 8 +- lib/jasmine-core/boot/node_boot.js | 71 +++++++ .../example/node_example/spec/PlayerSpec.js | 60 ++++++ .../example/node_example/spec/SpecHelper.js | 15 ++ .../example/node_example/src/Player.js | 24 +++ .../example/node_example/src/Song.js | 9 + lib/jasmine-core/node_boot.js | 93 +++++++++ package.json | 11 +- spec/helpers/nodeDefineJasmineUnderTest.js | 33 ++++ spec/node_suite.js | 187 ------------------ spec/support/jasmine-performance.json | 9 + spec/support/jasmine.json | 10 + spec/support/jasmine.yml | 3 +- 18 files changed, 379 insertions(+), 211 deletions(-) create mode 100644 .npmignore delete mode 100644 grunt/tasks/spec.js create mode 100644 lib/jasmine-core.js create mode 100644 lib/jasmine-core/boot/node_boot.js create mode 100644 lib/jasmine-core/example/node_example/spec/PlayerSpec.js create mode 100644 lib/jasmine-core/example/node_example/spec/SpecHelper.js create mode 100644 lib/jasmine-core/example/node_example/src/Player.js create mode 100644 lib/jasmine-core/example/node_example/src/Song.js create mode 100644 lib/jasmine-core/node_boot.js create mode 100644 spec/helpers/nodeDefineJasmineUnderTest.js delete mode 100644 spec/node_suite.js create mode 100644 spec/support/jasmine-performance.json create mode 100644 spec/support/jasmine.json diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..f131d95a --- /dev/null +++ b/.npmignore @@ -0,0 +1,23 @@ +dist/ +grunt/ +images/ +node_modules +release_notes/ +spec/ +src/ +Gemfile +Gemfile.lock +Rakefile +jasmine-core.gemspec +.rspec +.travis.yml +.jshintrc +.gitignore +*.sh +Gruntfile.js +lib/jasmine-core/boot/ +lib/jasmine-core/boot.js +lib/jasmine-core/spec +lib/jasmine-core/*.css +lib/jasmine-core/jasmine-html.js +lib/jasmine-core/version.rb diff --git a/Gruntfile.js b/Gruntfile.js index b67bd83d..f4319b7e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -34,11 +34,20 @@ module.exports = function(grunt) { ] ); - var spec = require('./grunt/tasks/spec.js'); - grunt.registerTask("execSpecsInNode", - "Run Jasmine core specs in Node.js", - spec.execSpecsInNode + "Run Jasmine core specs in Node.js", + function() { + var exitInfo = require("shelljs").exec("node_modules/.bin/jasmine"); + if (exitInfo.code !== 0) { + grunt.fail.fatal("Specs Failed", exitInfo.code); + } + } ); + grunt.registerTask("execSpecsInNode:performance", + "Run Jasmine performance specs in Node.js", + function() { + require("shelljs").exec("node_modules/.bin/jasmine JASMINE_CONFIG_PATH=spec/support/jasmine-performance.json"); + } + ); }; diff --git a/grunt/config/concat.js b/grunt/config/concat.js index 39770473..555a2f05 100644 --- a/grunt/config/concat.js +++ b/grunt/config/concat.js @@ -39,6 +39,10 @@ module.exports = { src: ['lib/jasmine-core/boot/boot.js'], dest: 'lib/jasmine-core/boot.js' }, + nodeBoot: { + src: ['lib/jasmine-core/boot/node_boot.js'], + dest: 'lib/jasmine-core/node_boot.js' + }, console: { src: [ 'src/console/requireConsole.js', diff --git a/grunt/tasks/spec.js b/grunt/tasks/spec.js deleted file mode 100644 index 2d9c6195..00000000 --- a/grunt/tasks/spec.js +++ /dev/null @@ -1,11 +0,0 @@ -var shell = require('shelljs'); -var grunt = require('grunt'); - -module.exports = { - execSpecsInNode: function() { - var exit_code = shell.exec("node spec/node_suite.js --color=true").code; - if (exit_code !== 0) { - grunt.fail.fatal("Specs Failed", exit_code); - } - } -}; diff --git a/lib/jasmine-core.js b/lib/jasmine-core.js new file mode 100644 index 00000000..4ab5e4c0 --- /dev/null +++ b/lib/jasmine-core.js @@ -0,0 +1,2 @@ +module.exports = require("./jasmine-core/jasmine.js"); +module.exports.boot = require('./jasmine-core/node_boot.js'); diff --git a/lib/jasmine-core.rb b/lib/jasmine-core.rb index c58760da..dc8682ec 100644 --- a/lib/jasmine-core.rb +++ b/lib/jasmine-core.rb @@ -6,7 +6,7 @@ module Jasmine end def js_files - (["jasmine.js"] + Dir.glob(File.join(path, "*.js"))).map { |f| File.basename(f) }.uniq - boot_files + (["jasmine.js"] + Dir.glob(File.join(path, "*.js"))).map { |f| File.basename(f) }.uniq - boot_files - node_boot_files end SPEC_TYPES = ["core", "html", "node"] @@ -27,8 +27,12 @@ module Jasmine ["boot.js"] end + def node_boot_files + ["node_boot.js"] + end + def boot_dir - File.join(path, 'boot') + path end def spec_files(type) diff --git a/lib/jasmine-core/boot/node_boot.js b/lib/jasmine-core/boot/node_boot.js new file mode 100644 index 00000000..bb93b7d0 --- /dev/null +++ b/lib/jasmine-core/boot/node_boot.js @@ -0,0 +1,71 @@ +module.exports = function(jasmineRequire) { + var jasmine = jasmineRequire.core(jasmineRequire); + + var consoleFns = require('../console/console.js'); + consoleFns.console(consoleFns, jasmine); + + var env = jasmine.getEnv(); + + var jasmineInterface = { + describe: function(description, specDefinitions) { + return env.describe(description, specDefinitions); + }, + + xdescribe: function(description, specDefinitions) { + return env.xdescribe(description, specDefinitions); + }, + + it: function(desc, func) { + return env.it(desc, func); + }, + + xit: function(desc, func) { + return env.xit(desc, func); + }, + + beforeEach: function(beforeEachFunction) { + return env.beforeEach(beforeEachFunction); + }, + + afterEach: function(afterEachFunction) { + return env.afterEach(afterEachFunction); + }, + + expect: function(actual) { + return env.expect(actual); + }, + + spyOn: function(obj, methodName) { + return env.spyOn(obj, methodName); + }, + + jsApiReporter: new jasmine.JsApiReporter({ + timer: new jasmine.Timer() + }), + + + jasmine: jasmine + }; + + extend(global, jasmineInterface); + + jasmine.addCustomEqualityTester = function(tester) { + env.addCustomEqualityTester(tester); + }; + + jasmine.addMatchers = function(matchers) { + return env.addMatchers(matchers); + }; + + jasmine.clock = function() { + return env.clock; + }; + + function extend(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; + } + + + return jasmine; +}; diff --git a/lib/jasmine-core/example/node_example/spec/PlayerSpec.js b/lib/jasmine-core/example/node_example/spec/PlayerSpec.js new file mode 100644 index 00000000..6d04bec4 --- /dev/null +++ b/lib/jasmine-core/example/node_example/spec/PlayerSpec.js @@ -0,0 +1,60 @@ +describe("Player", function() { + var Player = require('../../jasmine_examples/Player.js'); + var Song = require('../../jasmine_examples/Song.js'); + 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(); + }).toThrowError("song is already playing"); + }); + }); +}); diff --git a/lib/jasmine-core/example/node_example/spec/SpecHelper.js b/lib/jasmine-core/example/node_example/spec/SpecHelper.js new file mode 100644 index 00000000..578b3e86 --- /dev/null +++ b/lib/jasmine-core/example/node_example/spec/SpecHelper.js @@ -0,0 +1,15 @@ +beforeEach(function () { + jasmine.addMatchers({ + toBePlaying: function () { + return { + compare: function (actual, expected) { + var player = actual; + + return { + pass: player.currentlyPlayingSong === expected && player.isPlaying + } + } + }; + } + }); +}); diff --git a/lib/jasmine-core/example/node_example/src/Player.js b/lib/jasmine-core/example/node_example/src/Player.js new file mode 100644 index 00000000..fe95f894 --- /dev/null +++ b/lib/jasmine-core/example/node_example/src/Player.js @@ -0,0 +1,24 @@ +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); +}; + +module.exports = Player; diff --git a/lib/jasmine-core/example/node_example/src/Song.js b/lib/jasmine-core/example/node_example/src/Song.js new file mode 100644 index 00000000..3415bb82 --- /dev/null +++ b/lib/jasmine-core/example/node_example/src/Song.js @@ -0,0 +1,9 @@ +function Song() { +} + +Song.prototype.persistFavoriteStatus = function(value) { + // something complicated + throw new Error("not yet implemented"); +}; + +module.exports = Song; diff --git a/lib/jasmine-core/node_boot.js b/lib/jasmine-core/node_boot.js new file mode 100644 index 00000000..6c9b38c9 --- /dev/null +++ b/lib/jasmine-core/node_boot.js @@ -0,0 +1,93 @@ +/* +Copyright (c) 2008-2014 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +module.exports = function(jasmineRequire) { + var jasmine = jasmineRequire.core(jasmineRequire); + + var consoleFns = require('../console/console.js'); + consoleFns.console(consoleFns, jasmine); + + var env = jasmine.getEnv(); + + var jasmineInterface = { + describe: function(description, specDefinitions) { + return env.describe(description, specDefinitions); + }, + + xdescribe: function(description, specDefinitions) { + return env.xdescribe(description, specDefinitions); + }, + + it: function(desc, func) { + return env.it(desc, func); + }, + + xit: function(desc, func) { + return env.xit(desc, func); + }, + + beforeEach: function(beforeEachFunction) { + return env.beforeEach(beforeEachFunction); + }, + + afterEach: function(afterEachFunction) { + return env.afterEach(afterEachFunction); + }, + + expect: function(actual) { + return env.expect(actual); + }, + + spyOn: function(obj, methodName) { + return env.spyOn(obj, methodName); + }, + + jsApiReporter: new jasmine.JsApiReporter({ + timer: new jasmine.Timer() + }), + + + jasmine: jasmine + }; + + extend(global, jasmineInterface); + + jasmine.addCustomEqualityTester = function(tester) { + env.addCustomEqualityTester(tester); + }; + + jasmine.addMatchers = function(matchers) { + return env.addMatchers(matchers); + }; + + jasmine.clock = function() { + return env.clock; + }; + + function extend(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; + } + + + return jasmine; +}; diff --git a/package.json b/package.json index effa3a38..b3769aa2 100644 --- a/package.json +++ b/package.json @@ -8,17 +8,16 @@ }, "description": "Official packaging of Jasmine's core files for use by Node.js projects.", "homepage": "http://jasmine.github.io", - "files": [ - "lib/console", - "lib/jasmine-core" - ], + "main": "./lib/jasmine-core.js", "devDependencies": { "grunt": "~0.4.1", "grunt-contrib-jshint": "~0.7.0", "grunt-contrib-concat": "~0.3.0", "grunt-contrib-compass": "~0.6.0", "grunt-contrib-compress": "~0.5.2", - "load-grunt-tasks": "0.3.0", - "shelljs": "~0.1.4" + "shelljs": "~0.1.4", + "glob": "~3.2.9", + "jasmine": "https://github.com/pivotal/jasmine-npm/archive/master.tar.gz", + "load-grunt-tasks": "^0.4.0" } } diff --git a/spec/helpers/nodeDefineJasmineUnderTest.js b/spec/helpers/nodeDefineJasmineUnderTest.js new file mode 100644 index 00000000..4525ca10 --- /dev/null +++ b/spec/helpers/nodeDefineJasmineUnderTest.js @@ -0,0 +1,33 @@ +(function() { + var path = require("path"), + fs = require("fs"); + + var glob = require("glob"); + + var j$Require = require(path.join(__dirname, "../../src/core/requireCore.js")); + + global.getJasmineRequireObj = function () { + return j$Require; + }; + + function extend(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; + } + + function getSourceFiles() { + var src_files = ['core/**/*.js', 'console/**/*.js', 'version.js']; + src_files.forEach(function(file) { + var filePath = path.join(__dirname, "../../", 'src/', file); + glob.sync(filePath).forEach(function(resolvedFile) { + require(resolvedFile); + }); + }); + } + + extend(j$Require, require(path.join(__dirname,"../../src/console/requireConsole.js"))); + getSourceFiles(); + global.j$ = j$Require.core(j$Require); + + j$Require.console(j$Require, j$); +})(); diff --git a/spec/node_suite.js b/spec/node_suite.js deleted file mode 100644 index e2d3eeae..00000000 --- a/spec/node_suite.js +++ /dev/null @@ -1,187 +0,0 @@ -var fs = require('fs'); -var util = require('util'); -var path = require('path'); - -// boot code for jasmine -var jasmineRequire = require('../lib/jasmine-core/jasmine.js'); -var jasmine = jasmineRequire.core(jasmineRequire); - -var consoleFns = require('../lib/console/console.js'); -extend(jasmineRequire, consoleFns); -jasmineRequire.console(jasmineRequire, jasmine); - -var env = jasmine.getEnv(); - -var jasmineInterface = { - describe: function(description, specDefinitions) { - return env.describe(description, specDefinitions); - }, - - xdescribe: function(description, specDefinitions) { - return env.xdescribe(description, specDefinitions); - }, - - it: function(desc, func) { - return env.it(desc, func); - }, - - xit: function(desc, func) { - return env.xit(desc, func); - }, - - beforeEach: function(beforeEachFunction) { - return env.beforeEach(beforeEachFunction); - }, - - afterEach: function(afterEachFunction) { - return env.afterEach(afterEachFunction); - }, - - expect: function(actual) { - return env.expect(actual); - }, - - spyOn: function(obj, methodName) { - return env.spyOn(obj, methodName); - }, - - jsApiReporter: new jasmine.JsApiReporter({ - timer: new jasmine.Timer() - }) -}; - -extend(global, jasmineInterface); - -function extend(destination, source) { - for (var property in source) destination[property] = source[property]; - return destination; -} - -jasmine.addCustomEqualityTester = function(tester) { - env.addCustomEqualityTester(tester); -}; - -jasmine.addMatchers = function(matchers) { - return env.addMatchers(matchers); -}; - -jasmine.clock = function() { - return env.clock; -}; - -// Jasmine "runner" -function executeSpecs(specs, done, isVerbose, showColors) { - global.jasmine = jasmine; - - for (var i = 0; i < specs.length; i++) { - var filename = specs[i]; - require(filename.replace(/\.\w+$/, "")); - } - - var env = jasmine.getEnv(); - var consoleReporter = new jasmine.ConsoleReporter({ - print: util.print, - onComplete: done, - showColors: showColors, - timer: new jasmine.Timer() - }); - - env.addReporter(consoleReporter); - env.execute(); -} - -function getFiles(dir, matcher) { - var allFiles = []; - - if (fs.statSync(dir).isFile() && dir.match(matcher)) { - allFiles.push(dir); - } else { - var files = fs.readdirSync(dir); - for (var i = 0, len = files.length; i < len; ++i) { - var filename = dir + '/' + files[i]; - if (fs.statSync(filename).isFile() && filename.match(matcher)) { - allFiles.push(filename); - } else if (fs.statSync(filename).isDirectory()) { - var subfiles = getFiles(filename); - subfiles.forEach(function(result) { - allFiles.push(result); - }); - } - } - } - return allFiles; -} - -function getSpecFiles(dir) { - return getFiles(dir, new RegExp("Spec.js$")); -} - -var j$require = (function() { - var exported = {}, - j$req; - - global.getJasmineRequireObj = getJasmineRequireObj; - - j$req = require(__dirname + "/../src/core/requireCore.js"); - extend(j$req, require(__dirname + "/../src/console/requireConsole.js")); - - var srcFiles = getFiles(__dirname + "/../src/core"); - srcFiles.push(__dirname + "/../src/version.js"); - srcFiles.push(__dirname + "/../src/console/ConsoleReporter.js"); - - for (var i = 0; i < srcFiles.length; i++) { - require(srcFiles[i]); - } - extend(j$req, exported); - - delete global.getJasmineRequireObj; - - return j$req; - - function getJasmineRequireObj() { - return exported; - } -}()); - -j$ = j$require.core(j$require); -j$require.console(j$require, j$); - -// options from command line -var isVerbose = false; -var showColors = true; -var perfSuite = false; - -process.argv.forEach(function(arg) { - switch (arg) { - case '--color': - showColors = true; - break; - case '--noColor': - showColors = false; - break; - case '--verbose': - isVerbose = true; - break; - case '--perf': - perfSuite = true; - break; - } -}); - -specs = []; - -if (perfSuite) { - specs = getFiles(__dirname + '/performance', new RegExp("test.js$")); -} else { - var consoleSpecs = getSpecFiles(__dirname + "/console"), - coreSpecs = getSpecFiles(__dirname + "/core"), - specs = consoleSpecs.concat(coreSpecs); -} - -executeSpecs(specs, function(passed) { - if (passed) { - process.exit(0); - } else { - process.exit(1); - } -}, isVerbose, showColors); diff --git a/spec/support/jasmine-performance.json b/spec/support/jasmine-performance.json new file mode 100644 index 00000000..d1a80463 --- /dev/null +++ b/spec/support/jasmine-performance.json @@ -0,0 +1,9 @@ +{ + "spec_dir": "spec", + "spec_files": [ + "performance/performance_test.js" + ], + "helper_files": [ + "helpers/nodeDefineJasmineUnderTest.js" + ] +} diff --git a/spec/support/jasmine.json b/spec/support/jasmine.json new file mode 100644 index 00000000..8583679e --- /dev/null +++ b/spec/support/jasmine.json @@ -0,0 +1,10 @@ +{ + "spec_dir": "spec", + "spec_files": [ + "core/**/*.js", + "console/**/*.js" + ], + "helpers": [ + "helpers/nodeDefineJasmineUnderTest.js" + ] +} diff --git a/spec/support/jasmine.yml b/spec/support/jasmine.yml index ec89b429..4a8ecb0a 100644 --- a/spec/support/jasmine.yml +++ b/spec/support/jasmine.yml @@ -16,7 +16,8 @@ src_files: - '**/*.js' stylesheets: helpers: - - 'helpers/**/*.js' + - 'helpers/BrowserFlags.js' + - 'helpers/defineJasmineUnderTest.js' spec_files: - '**/*[Ss]pec.js' spec_dir: spec