Updated to latest jasmine version

This commit is contained in:
Rajan Agaskar 2009-04-22 08:00:04 -07:00
parent 2032f51460
commit a3ea7c7c47
34 changed files with 5243 additions and 0 deletions

5
.idea/encodings.xml generated Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project relativePaths="false" version="4">
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
</project>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0" is_locked="false">
<option name="myName" value="Project Default" />
<option name="myLocal" value="false" />
</profile>
</component>

View File

@ -0,0 +1,8 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="PROJECT_PROFILE" value="Project Default" />
<option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
<scopes />
<list size="0" />
</settings>
</component>

9
.idea/jasmine_git.iml generated Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module relativePaths="false" type="RUBY_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

14
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project relativePaths="false" version="4">
<component name="DependencyValidationManager">
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</component>
<component name="ProjectDetails">
<option name="projectName" value="jasmine_git" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Ruby SDK 1.8.6 (/usr/bin/ruby)" project-jdk-type="RUBY_SDK" />
<component name="SvnBranchConfigurationManager">
<option name="mySupportsUserInfoFilter" value="true" />
</component>
</project>

9
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project relativePaths="false" version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/jasmine_git.iml" filepath="$PROJECT_DIR$/.idea/jasmine_git.iml" />
</modules>
</component>
</project>

8
.idea/projectCodeStyle.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project relativePaths="false" version="4">
<component name="CodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS" />
<option name="USE_PER_PROJECT_SETTINGS" value="false" />
</component>
</project>

8
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project relativePaths="false" version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

237
.idea/workspace.xml generated Normal file
View File

@ -0,0 +1,237 @@
<?xml version="1.0" encoding="UTF-8"?>
<project relativePaths="false" version="4">
<component name="ChangeListManager">
<list default="true" readonly="true" name="Default" comment="" />
<ignored path="jasmine_git.iws" />
<ignored path=".idea/workspace.xml" />
</component>
<component name="ChangesViewManager" flattened_view="true" show_ignored="false" />
<component name="CreatePatchCommitExecutor">
<option name="PATCH_PATH" value="" />
<option name="REVERSE_PATCH" value="false" />
</component>
<component name="DaemonCodeAnalyzer">
<disable_hints />
</component>
<component name="FavoritesManager">
<favorites_list name="jasmine_git" />
</component>
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="bootstrap.js" pinned="false" current="true" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/test/test/bootstrap.js">
<provider selected="true" editor-type-id="text-editor">
<state line="1815" column="36" selection-start="62956" selection-end="62956" vertical-scroll-proportion="0.18728323">
<folding />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FindManager">
<FindUsagesManager>
<setting name="OPEN_NEW_TAB" value="false" />
</FindUsagesManager>
</component>
<component name="ProjectLevelVcsManager">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectPane">
<subPane>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="test" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="test" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="test" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="test" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="lib" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="lib" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine_git" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="images" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</component>
<component name="ProjectReloadState">
<option name="STATE" value="0" />
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="0.5" version="1" splitterProportion="0.5">
<flattenPackages />
<showMembers />
<showModules />
<showLibraryContents />
<hideEmptyPackages />
<abbreviatePackageNames />
<showStructure ProjectPane="false" />
<autoscrollToSource />
<autoscrollFromSource />
<sortByType />
</navigator>
</component>
<component name="RunManager">
<list size="0" />
</component>
<component name="ShelveChangesManager" show_recycled="false" />
<component name="SvnConfiguration">
<option name="USER" value="" />
<option name="PASSWORD" value="" />
<option name="LAST_MERGED_REVISION" />
<option name="UPDATE_RUN_STATUS" value="false" />
<option name="MERGE_DRY_RUN" value="false" />
<option name="MERGE_DIFF_USE_ANCESTRY" value="true" />
<option name="UPDATE_LOCK_ON_DEMAND" value="false" />
<option name="IGNORE_SPACES_IN_MERGE" value="false" />
<option name="DETECT_NESTED_COPIES" value="true" />
<configuration useDefault="true">/Users/ragaskar/.subversion</configuration>
<myIsUseDefaultProxy>false</myIsUseDefaultProxy>
<supportedVersion>124</supportedVersion>
</component>
<component name="ToolWindowManager">
<frame x="3" y="22" width="1619" height="1028" extended-state="0" />
<editor active="true" />
<layout>
<window_info id="Web Preview" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" />
<window_info id="Dependency Viewer" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" />
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.24952978" sideWeight="0.5" order="0" side_tool="false" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="3" side_tool="false" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="1" side_tool="false" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" />
</layout>
</component>
<component name="VcsManagerConfiguration">
<option name="OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT" value="true" />
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="true" />
<option name="PERFORM_UPDATE_IN_BACKGROUND" value="true" />
<option name="PERFORM_COMMIT_IN_BACKGROUND" value="true" />
<option name="PERFORM_EDIT_IN_BACKGROUND" value="true" />
<option name="PERFORM_CHECKOUT_IN_BACKGROUND" value="true" />
<option name="PERFORM_ADD_REMOVE_IN_BACKGROUND" value="true" />
<option name="PERFORM_ROLLBACK_IN_BACKGROUND" value="false" />
<option name="FORCE_NON_EMPTY_COMMENT" value="false" />
<option name="LAST_COMMIT_MESSAGE" />
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="false" />
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="false" />
<option name="REFORMAT_BEFORE_FILE_COMMIT" value="false" />
<option name="FILE_HISTORY_DIALOG_COMMENTS_SPLITTER_PROPORTION" value="0.8" />
<option name="FILE_HISTORY_DIALOG_SPLITTER_PROPORTION" value="0.5" />
<option name="ACTIVE_VCS_NAME" />
<option name="UPDATE_GROUP_BY_PACKAGES" value="false" />
<option name="UPDATE_GROUP_BY_CHANGELIST" value="false" />
<option name="SHOW_FILE_HISTORY_AS_TREE" value="false" />
<option name="FILE_HISTORY_SPLITTER_PROPORTION" value="0.6" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/test/test/bootstrap.js">
<provider selected="true" editor-type-id="text-editor">
<state line="1815" column="36" selection-start="62956" selection-end="62956" vertical-scroll-proportion="0.18728323">
<folding />
</state>
</provider>
</entry>
</component>
</project>

20
test/MIT.LICENSE Normal file
View File

@ -0,0 +1,20 @@
Copyright (c) 2008 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.

210
test/README.markdown Normal file
View File

@ -0,0 +1,210 @@
Jasmine
=======
**YET ANOTHER JavaScript testing framework**
Why Another Frickin' JS TDD/BDD Framework?
-----------
There are some situations when you want to test-drive JavaScript, but you don't want to be bothered with or even have an explicit document. You have no DOM to work with and thus lack HTML elements on which to hang event handlers. You may need to make asynchronous calls (say, to an AJAX API) and cannot mock/stub them.
But you still need to write tests.
What's an Agile Engineer to do?
Enter Jasmine
------------
Jasmine is yet another JavaScript testing framework. It's *heavily* influenced by JSSpec, ScrewUnit & [JSpec](http://github.com/visionmedia/jspec/tree/master), which are all influenced by RSpec. But each of those was lacking in some way: JSSpec & ScrewUnit require a DOM. JSpec's DOM-less assumption was a great start, but it needed asynchronous support.
So we started over. And TDD'd a whole new framework. Enjoy.
How To
------
There is a nice example of how to use Jasmine in the /example directory. But here's more information.
### Specs
Each spec is, naturally, a JavaScript function. You tell Jasmine about this spec with a call to `it()` with a name and the function. The string is a description that will be helpful to you when reading a report.
Your spec needs to call `runs()` with another function that is the actual spec. More on why in a moment. Here's an example:
it('should be a test', function () {
runs(function () {
var foo = 0
foo++;
});
});
### Expectations
Within your spec you will want/need to make expectations. These are made like this:
it('should be a test', function () {
runs(function () {
var foo = 0
foo++;
this.expects_that(foo).should_equal(1);
});
});
Results of the expectations are logged for later for reporting.
### Multiple Calls to `runs()` & Scope in Your Spec
Your spec can call `runs()` multiple times if you need to break your spec up for any reason. Say, for async support (see next section). To allow you to share variables across your `runs()` functions, `this` is set to the spec itself. For example:
it('should be a test', function () {
runs(function () {
this.foo = 0
this.foo++;
this.expects_that(this.foo).should_equal(1);
});
runs(function () {
this.foo++;
this.expects_that(this.foo).should_equal(2);
})
});
Functions defined with `runs()` are called in the order in which they are defined.
### Asynchronous Specs
You may be asking yourself, "Self, why would I ever need to break up my tests into pieces like this?" The answer is when dealing with asynchronous function calls.
Say you need to make a call that is asynchronous - an AJAX API, or some other JavaScript library. That is, the call returns immediately, yet you want to make expectations 'at some point in the future' after some magic happens in the background.
Jasmine allows you to do this by chaining calls to `runs()` with calls to `waits()`. You supply a time to wait before the next `runs()` function is executed. Such as:
it('should be a test', function () {
runs(function () {
this.foo = 0;
var that = this;
setTimeout(function () {
that.foo++;
}, 250);
});
runs(function () {
this.expects_that(this.foo).should_equal(0);
});
waits(500);
runs(function () {
this.expects_that(this.foo).should_equal(1);
});
});
What's happening here?
* The first call to `runs()` sets call for 1/4 of a second in the future that increments `this.foo`.
* The second `runs()` is executed immediately and then verifies that `this.foo` was indeed initialized to zero in the previous `runs()`.
* Then we wait for half a second.
* Then the last call to `runs()` expects that `this.foo` was incremented by the `setTimeout`.
### Suites
Specs are grouped in Suites. Suites are defined using the global `describe()` function:
describe('One suite', function () {
it('has a test', function () {
...
});
it('has another test', function () {
...
});
});
The name is so that reporting is more descriptive.
Suites are executed in the order in which `describe()` calls are made, usually in the order in which their script files are included.
### Runner
You don't need a DOM to run your tests, but you do need a page on which to load & execute your JS. Include the `jasmine.js` file in a script tag as well as the JS file with your specs. You can also use this page for reporting. More on that in a moment.
Here's the example HTML file (in `jasmine/example`):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Example</title>
<script type="text/javascript" src="../lib/jasmine.js"></script>
<script type="text/javascript" src="example.js"></script>
<link type="text/css" rel="stylesheet" href="../lib/jasmine.css"/>
</head>
<body>
<h1>
Running Jasmine Example Specs
</h1>
<div id="results"></div>
<script type="text/javascript">
jasmine.execute();
setTimeout(function () {
document.getElementById('results').innerHTML = 'It\'s alive! :' +
(jasmine.currentRunner.results.passedCount === 1);
}, 250);
</script>
</body>
</html>
### Reports
If a reporter exists on the Jasmine instance (named `jasmine`), it will be called when each spec, suite and the overall runner complete. If you're at the single-spec result level, you'll get a spec description, whether it passed or failed, and what the failure message was. At the suite & runner report level, you'll get the total specs run so far, the passed counts, failed counts, and a description (of the suite or runner).
There is a `Jasmine.Reporters` namespace for you to see how to handle reporting. See the file `json_reporter.js`, which takes the results objects and turns them into JSON strings, for two examples of how to make the results callbacks work for you.
### Custom Matchers
Jasmine has a simple set of matchers - currently just should\_equal and should\_not\_equal. But Matchers can be extended simply to add new expectations. We use Douglas Crockford's Function.method() helper to define new Matchers.
A Matcher has a method name, takes an expected value as it's only parameter, has access to the actual value in this, and then makes a call to this.report with true/false with a failure message. Here's the definition of should\_equal():
Matchers.method('should_equal', function (expected) {
return this.report((this.actual === expected),
'Expected ' + expected + ' but got ' + this.actual + '.');
});
Feel free to define your own matcher as needed in your code. If you'd like to add Matchers to Jasmine, please write tests.
### Limitations
You can only have one instance of Jasmine (which is a container for a runner) running at any given time. As you can see from `bootstrap.js`, this means you have to wait until a runner is done before defining suites & specs for another runner.
This is a bit sloppy and will be fixed at some point - but it allows for a nicer syntax when defining your specs. For now we expect this to be fine as most of the time having multiple suites is sufficient for isolating application-level code.
Contributing and Tests
----------------------
Sometimes it's hard to test a framework with the framework itself. Either the framework isn't mature enough or it just hurts your head. Jasmine is affected by both.
So we made a little bootstrappy test reporter that lets us test Jasmine's pieces in isolation. See test/bootstrap.js. Feel free to use the bootstrap test suite to test your custom Matchers or extensions/changes to Jasmine.
Your contributions are welcome. Please submit tests with your pull request.
## Maintainers
* [Davis W. Frank](dwfrank@pivotallabs.com), Pivotal Labs
* [Rajan Agaskar](rajan@pivotallabs.com), Pivotal Labs
## Acknowledgments
* A big shout out to the various JavaScript test framework authors, especially TJ for [JSpec](http://github.com/visionmedia/jspec/tree/master) - we played with it a bit before deciding that we really needed to roll our own.
* Thanks to Pivot [Jessica Miller](http://www.jessicamillerworks.com/) for our fancy pass/fail/pending icons
## TODO List
In no particular order:
* Maybe add a description to `runs()` that gets incorporated in the message somehow?
* Empty specs - calls to `it()` without a function - should be considered Pending specs and have their numbers rolled up for reporting.
* Exception catching doesn't work after a call to `waits()`
* Add it `xit()` convention for disabled specs
* Pending & Disabled counts should be included in results

25
test/example/example.html Normal file
View File

@ -0,0 +1,25 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Example</title>
<script type="text/javascript" src="../lib/jasmine.js"></script>
<script type="text/javascript" src="example.js"></script>
<link type="text/css" rel="stylesheet" href="../lib/jasmine.css"/>
</head>
<body>
<h1>
Running Jasmine Example Specs
</h1>
<div id="results"></div>
<script type="text/javascript">
jasmine.getEnv().execute();
setTimeout(function () {
document.getElementById('results').innerHTML = 'It\'s alive! :' +
(jasmine.getEnv().currentRunner.results.passedCount === 1);
}, 250);
</script>
</body>
</html>

7
test/example/example.js Normal file
View File

@ -0,0 +1,7 @@
describe('one suite description', function () {
it('should be a test', function() {
runs(function () {
expect(true).toEqual(true);
});
});
});

BIN
test/images/fail-16.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

BIN
test/images/fail.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
test/images/go-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 759 B

BIN
test/images/go.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
test/images/pending-16.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 B

BIN
test/images/pending.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
test/images/question-bk.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
test/images/questionbk-16.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 B

BIN
test/images/spinner.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

17
test/jasmine.iml Executable file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module relativePaths="true" type="RUBY_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="false">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Ruby SDK" jdkType="RUBY_SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntryProperties />
</component>
<component name="RModuleContentRootManager">
<TEST_URLS url="file://$MODULE_DIR$/test" />
</component>
<component name="RModuleSettingsStorage">
<RMODULE_SETTINGS_STORAGE_ID NAME="SHOULD_USE_RSPEC_TEST_FRAMEWORK" VALUE="false" />
<RMODULE_SETTINGS_STORAGE_ID NAME="NUMBER" VALUE="0" />
</component>
</module>

250
test/jasmine.ipr Executable file
View File

@ -0,0 +1,250 @@
<?xml version="1.0" encoding="UTF-8"?>
<project relativePaths="false" version="4">
<component name="BuildJarProjectSettings">
<option name="BUILD_JARS_ON_MAKE" value="false" />
</component>
<component name="CodeStyleProjectProfileManger">
<option name="PROJECT_PROFILE" />
<option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
</component>
<component name="CodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS" />
<option name="USE_PER_PROJECT_SETTINGS" value="false" />
</component>
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
<option name="DEPLOY_AFTER_MAKE" value="0" />
<resourceExtensions>
<entry name=".+\.(properties|xml|html|dtd|tld)" />
<entry name=".+\.(gif|png|jpeg|jpg)" />
</resourceExtensions>
<wildcardResourcePatterns>
<entry name="?*.properties" />
<entry name="?*.xml" />
<entry name="?*.gif" />
<entry name="?*.png" />
<entry name="?*.jpeg" />
<entry name="?*.jpg" />
<entry name="?*.html" />
<entry name="?*.dtd" />
<entry name="?*.tld" />
</wildcardResourcePatterns>
</component>
<component name="DependenciesAnalyzeManager">
<option name="myForwardDirection" value="false" />
</component>
<component name="DependencyValidationManager">
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</component>
<component name="EclipseCompilerSettings">
<option name="DEBUGGING_INFO" value="true" />
<option name="GENERATE_NO_WARNINGS" value="true" />
<option name="DEPRECATION" value="false" />
<option name="ADDITIONAL_OPTIONS_STRING" value="" />
<option name="MAXIMUM_HEAP_SIZE" value="128" />
</component>
<component name="EclipseEmbeddedCompilerSettings">
<option name="DEBUGGING_INFO" value="true" />
<option name="GENERATE_NO_WARNINGS" value="true" />
<option name="DEPRECATION" value="false" />
<option name="ADDITIONAL_OPTIONS_STRING" value="" />
<option name="MAXIMUM_HEAP_SIZE" value="128" />
</component>
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="IdProvider" IDEtalkID="C14C40869794AC3CAF20CE1030F0B441" />
<component name="InspectionProjectProfileManager">
<option name="PROJECT_PROFILE" value="Project Default" />
<option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
<scopes />
<profiles>
<profile version="1.0" is_locked="false">
<option name="myName" value="Project Default" />
<option name="myLocal" value="false" />
</profile>
</profiles>
<list size="0" />
</component>
<component name="JavacSettings">
<option name="DEBUGGING_INFO" value="true" />
<option name="GENERATE_NO_WARNINGS" value="false" />
<option name="DEPRECATION" value="true" />
<option name="ADDITIONAL_OPTIONS_STRING" value="" />
<option name="MAXIMUM_HEAP_SIZE" value="128" />
</component>
<component name="JavadocGenerationManager">
<option name="OUTPUT_DIRECTORY" />
<option name="OPTION_SCOPE" value="protected" />
<option name="OPTION_HIERARCHY" value="true" />
<option name="OPTION_NAVIGATOR" value="true" />
<option name="OPTION_INDEX" value="true" />
<option name="OPTION_SEPARATE_INDEX" value="true" />
<option name="OPTION_DOCUMENT_TAG_USE" value="false" />
<option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
<option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
<option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
<option name="OPTION_DEPRECATED_LIST" value="true" />
<option name="OTHER_OPTIONS" value="" />
<option name="HEAP_SIZE" />
<option name="LOCALE" />
<option name="OPEN_IN_BROWSER" value="true" />
</component>
<component name="JikesSettings">
<option name="JIKES_PATH" value="" />
<option name="DEBUGGING_INFO" value="true" />
<option name="DEPRECATION" value="true" />
<option name="GENERATE_NO_WARNINGS" value="false" />
<option name="IS_EMACS_ERRORS_MODE" value="true" />
<option name="ADDITIONAL_OPTIONS_STRING" value="" />
</component>
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
<component name="ProjectFileVersion" converted="true" />
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/jasmine.iml" filepath="$PROJECT_DIR$/jasmine.iml" />
</modules>
</component>
<component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="true" project-jdk-name="Ruby SDK" project-jdk-type="RUBY_SDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="ResourceManagerContainer">
<option name="myResourceBundles">
<value>
<list size="0" />
</value>
</option>
</component>
<component name="RmicSettings">
<option name="IS_EANABLED" value="false" />
<option name="DEBUGGING_INFO" value="true" />
<option name="GENERATE_NO_WARNINGS" value="false" />
<option name="GENERATE_IIOP_STUBS" value="false" />
<option name="ADDITIONAL_OPTIONS_STRING" value="" />
</component>
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
<component name="WebServicesPlugin" addRequiredLibraries="true" />
</project>

565
test/jasmine.iws Normal file
View File

@ -0,0 +1,565 @@
<?xml version="1.0" encoding="UTF-8"?>
<project relativePaths="false" version="4">
<component name="CCaseConfig">
<option name="checkoutReserved" value="false" />
<option name="markExternalChangeAsUpToDate" value="true" />
<option name="checkInUseHijack" value="true" />
<option name="useUcmModel" value="true" />
<option name="isOffline" value="false" />
<option name="synchOutside" value="false" />
<option name="isHistoryResticted" value="true" />
<option name="useIdenticalSwitch" value="true" />
<option name="synchActivitiesOnRefresh" value="true" />
<option name="lastScr" value="" />
<option name="scrTextFileName" value="" />
<option name="historyRevisionsNumber" value="4" />
</component>
<component name="ChangeListManager">
<list default="true" name="Default" comment="" />
<ignored path="jasmine.iws" />
<ignored path=".idea/workspace.xml" />
</component>
<component name="ChangesViewManager" flattened_view="true" show_ignored="false" />
<component name="Commander">
<leftPanel />
<rightPanel />
<splitter proportion="0.5" />
</component>
<component name="CreatePatchCommitExecutor">
<option name="PATCH_PATH" value="" />
<option name="REVERSE_PATCH" value="false" />
</component>
<component name="DaemonCodeAnalyzer">
<disable_hints />
</component>
<component name="DebuggerManager">
<breakpoint_any>
<breakpoint>
<option name="NOTIFY_CAUGHT" value="true" />
<option name="NOTIFY_UNCAUGHT" value="true" />
<option name="ENABLED" value="false" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
<breakpoint>
<option name="NOTIFY_CAUGHT" value="true" />
<option name="NOTIFY_UNCAUGHT" value="true" />
<option name="ENABLED" value="false" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
</breakpoint_any>
<breakpoint_rules />
<ui_properties />
</component>
<component name="ErrorTreeViewConfiguration">
<option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
<option name="HIDE_WARNINGS" value="false" />
</component>
<component name="FavoritesManager">
<favorites_list name="jasmine" />
</component>
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="bootstrap.html" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/test/bootstrap.html">
<provider selected="true" editor-type-id="text-editor">
<state line="12" column="4" selection-start="533" selection-end="533" vertical-scroll-proportion="0.23799582">
<folding />
</state>
</provider>
<provider editor-type-id="HtmlPreview">
<state />
</provider>
</entry>
</file>
<file leaf-file-name="bootstrap.js" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/test/bootstrap.js">
<provider selected="true" editor-type-id="text-editor">
<state line="861" column="1" selection-start="26398" selection-end="26398" vertical-scroll-proportion="0.6571146">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="jasmine.js" pinned="false" current="true" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/lib/jasmine.js">
<provider selected="true" editor-type-id="text-editor">
<state line="265" column="7" selection-start="5960" selection-end="5960" vertical-scroll-proportion="0.13286713">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="example.html" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/example.html">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="721" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
<provider editor-type-id="HtmlPreview">
<state />
</provider>
</entry>
</file>
<file leaf-file-name="jasmine.css" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/jasmine.css">
<provider selected="true" editor-type-id="text-editor">
<state line="17" column="36" selection-start="351" selection-end="351" vertical-scroll-proportion="0.3145083">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="example.js" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/example.js">
<provider selected="true" editor-type-id="text-editor">
<state line="6" column="0" selection-start="183" selection-end="183" vertical-scroll-proportion="0.11100292">
<folding />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FindManager">
<FindUsagesManager>
<setting name="OPEN_NEW_TAB" value="false" />
</FindUsagesManager>
</component>
<component name="HierarchyBrowserManager">
<option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
<option name="SORT_ALPHABETICALLY" value="false" />
<option name="HIDE_CLASSES_WHERE_METHOD_NOT_IMPLEMENTED" value="false" />
</component>
<component name="ModuleEditorState">
<option name="LAST_EDITED_MODULE_NAME" />
<option name="LAST_EDITED_TAB_NAME" />
</component>
<component name="ProjectLevelVcsManager">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<OptionsSetting value="true" id="Undo Check Out" />
<OptionsSetting value="true" id="Get Latest Version" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectPane">
<subPane>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="PsiDirectory:/Users/pivotal/workspace/jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="PsiDirectory:/Users/pivotal/workspace/jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="PsiDirectory:/Users/pivotal/workspace/jasmine/test" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="PsiDirectory:/Users/pivotal/workspace/jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="PsiDirectory:/Users/pivotal/workspace/jasmine/lib" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="PsiDirectory:/Users/pivotal/workspace/jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="PsiDirectory:/Users/pivotal/workspace/jasmine/images" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="PsiDirectory:/Users/pivotal/workspace/jasmine" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="PsiDirectory:/Users/pivotal/workspace/jasmine/example" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</component>
<component name="ProjectReloadState">
<option name="STATE" value="0" />
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="0.11111111" version="1" splitterProportion="0.5">
<flattenPackages />
<showMembers />
<showModules />
<showLibraryContents />
<hideEmptyPackages />
<abbreviatePackageNames />
<showStructure ProjectPane="false" />
<autoscrollToSource />
<autoscrollFromSource />
<sortByType />
</navigator>
</component>
<component name="PropertiesComponent">
<property name="GoToClass.includeJavaFiles" value="false" />
<property name="MemberChooser.copyJavadoc" value="false" />
<property name="GoToClass.includeLibraries" value="false" />
<property name="MemberChooser.showClasses" value="true" />
<property name="MemberChooser.sorted" value="false" />
<property name="GoToFile.includeJavaFiles" value="false" />
<property name="GoToClass.toSaveIncludeLibraries" value="false" />
</component>
<component name="RubyDocSettings">
<RUBY_DOC NAME="DEFAULTS" VALUE="true" />
<RUBY_DOC NAME="NUMBER" VALUE="0" />
</component>
<component name="RunManager">
<configuration default="true" type="Remote" factoryName="Remote">
<option name="USE_SOCKET_TRANSPORT" value="true" />
<option name="SERVER_MODE" value="false" />
<option name="SHMEM_ADDRESS" value="javadebug" />
<option name="HOST" value="localhost" />
<option name="PORT" value="5005" />
</configuration>
<configuration default="true" type="RubyRunConfigurationType" factoryName="Ruby test">
<RTEST_RUN_CONFIG_SETTINGS_ID NAME="TESTS_FOLDER_PATH" VALUE="" />
<RTEST_RUN_CONFIG_SETTINGS_ID NAME="TEST_SCRIPT_PATH" VALUE="" />
<RTEST_RUN_CONFIG_SETTINGS_ID NAME="TEST_CLASS_NAME" VALUE="" />
<RTEST_RUN_CONFIG_SETTINGS_ID NAME="TEST_FILE_MASK" VALUE="" />
<RTEST_RUN_CONFIG_SETTINGS_ID NAME="TEST_METHOD_NAME" VALUE="" />
<RTEST_RUN_CONFIG_SETTINGS_ID NAME="TEST_TEST_TYPE" VALUE="TEST_SCRIPT" />
<RTEST_RUN_CONFIG_SETTINGS_ID NAME="RUBY_ARGS" VALUE="-e STDOUT.sync=true;STDERR.sync=true;load($0=ARGV.shift)" />
<RTEST_RUN_CONFIG_SETTINGS_ID NAME="WORK DIR" VALUE="" />
<RTEST_RUN_CONFIG_SETTINGS_ID NAME="MODULE_NAME" VALUE="" />
<RTEST_RUN_CONFIG_SETTINGS_ID NAME="SHOULD_USE_SDK" VALUE="false" />
<RTEST_RUN_CONFIG_SETTINGS_ID NAME="ALTERN_SDK_NAME" VALUE="" />
<RTEST_RUN_CONFIG_SETTINGS_ID NAME="INHERITANCE_CHECK_DISABLED" VALUE="false" />
</configuration>
<configuration default="true" type="Applet" factoryName="Applet">
<module name="" />
<option name="MAIN_CLASS_NAME" />
<option name="HTML_FILE_NAME" />
<option name="HTML_USED" value="false" />
<option name="WIDTH" value="400" />
<option name="HEIGHT" value="300" />
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
<option name="VM_PARAMETERS" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
</configuration>
<configuration default="true" type="Application" factoryName="Application" enabled="false" merge="false">
<option name="MAIN_CLASS_NAME" />
<option name="VM_PARAMETERS" />
<option name="PROGRAM_PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="ENABLE_SWING_INSPECTOR" value="false" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<module name="" />
<envs />
</configuration>
<configuration default="true" type="JUnit" factoryName="JUnit" enabled="false" merge="false">
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" />
<option name="MAIN_CLASS_NAME" />
<option name="METHOD_NAME" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" />
<option name="PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="ADDITIONAL_CLASS_PATH" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs />
</configuration>
<list size="0" />
<configuration name="&lt;template&gt;" type="WebApp" default="true" selected="false">
<Host>localhost</Host>
<Port>5050</Port>
</configuration>
</component>
<component name="StarteamConfiguration">
<option name="SERVER" value="" />
<option name="PORT" value="49201" />
<option name="USER" value="" />
<option name="PASSWORD" value="" />
<option name="PROJECT" value="" />
<option name="VIEW" value="" />
<option name="ALTERNATIVE_WORKING_PATH" value="" />
<option name="LOCK_ON_CHECKOUT" value="false" />
<option name="UNLOCK_ON_CHECKIN" value="false" />
</component>
<component name="StructureViewFactory">
<option name="AUTOSCROLL_MODE" value="true" />
<option name="AUTOSCROLL_FROM_SOURCE" value="false" />
<option name="ACTIVE_ACTIONS" value="" />
</component>
<component name="SvnConfiguration">
<option name="USER" value="" />
<option name="PASSWORD" value="" />
<option name="LAST_MERGED_REVISION" />
<option name="UPDATE_RUN_STATUS" value="false" />
<option name="UPDATE_RECURSIVELY" value="true" />
<option name="MERGE_DRY_RUN" value="false" />
</component>
<component name="TodoView" selected-index="0">
<todo-panel id="selected-file">
<are-packages-shown value="false" />
<are-modules-shown value="false" />
<flatten-packages value="false" />
<is-autoscroll-to-source value="true" />
</todo-panel>
<todo-panel id="all">
<are-packages-shown value="true" />
<are-modules-shown value="false" />
<flatten-packages value="false" />
<is-autoscroll-to-source value="true" />
</todo-panel>
<todo-panel id="default-changelist">
<are-packages-shown value="false" />
<are-modules-shown value="false" />
<flatten-packages value="false" />
<is-autoscroll-to-source value="false" />
</todo-panel>
</component>
<component name="ToolWindowManager">
<frame x="26" y="22" width="1833" height="1171" extended-state="0" />
<editor active="true" />
<layout>
<window_info id="UI Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="3" />
<window_info id="IDEtalk" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="3" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="7" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.2102018" order="0" />
<window_info id="RDoc" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="8" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32837301" order="1" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" order="1" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="14" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" order="6" />
<window_info id="Module Dependencies" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="6" />
<window_info id="Dependency Viewer" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="11" />
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="4" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" order="1" />
<window_info id="Maven projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="5" />
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="12" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="2" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" order="2" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" order="0" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" order="4" />
<window_info id="IDEtalk Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="13" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="9" />
<window_info id="Duplicates" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="10" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="0" />
<window_info id="Web" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" order="2" />
<window_info id="EJB" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" order="3" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" order="5" />
</layout>
</component>
<component name="VcsManagerConfiguration">
<option name="OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT" value="true" />
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="true" />
<option name="PERFORM_UPDATE_IN_BACKGROUND" value="false" />
<option name="PERFORM_COMMIT_IN_BACKGROUND" value="false" />
<option name="PERFORM_EDIT_IN_BACKGROUND" value="true" />
<option name="PERFORM_ADD_REMOVE_IN_BACKGROUND" value="true" />
<option name="FORCE_NON_EMPTY_COMMENT" value="false" />
<option name="LAST_COMMIT_MESSAGE" />
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="false" />
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="false" />
<option name="REFORMAT_BEFORE_FILE_COMMIT" value="false" />
<option name="FILE_HISTORY_DIALOG_COMMENTS_SPLITTER_PROPORTION" value="0.8" />
<option name="FILE_HISTORY_DIALOG_SPLITTER_PROPORTION" value="0.5" />
<option name="ACTIVE_VCS_NAME" />
<option name="UPDATE_GROUP_BY_PACKAGES" value="false" />
<option name="UPDATE_GROUP_BY_CHANGELIST" value="false" />
<option name="SHOW_FILE_HISTORY_AS_TREE" value="false" />
<option name="FILE_HISTORY_SPLITTER_PROPORTION" value="0.6" />
</component>
<component name="VssConfiguration">
<option name="CLIENT_PATH" value="" />
<option name="SRCSAFEINI_PATH" value="" />
<option name="USER_NAME" value="" />
<option name="PWD" value="" />
<CheckoutOptions>
<option name="COMMENT" value="" />
<option name="DO_NOT_GET_LATEST_VERSION" value="false" />
<option name="REPLACE_WRITABLE" value="false" />
<option name="RECURSIVE" value="false" />
</CheckoutOptions>
<CheckinOptions>
<option name="COMMENT" value="" />
<option name="KEEP_CHECKED_OUT" value="false" />
<option name="RECURSIVE" value="false" />
</CheckinOptions>
<AddOptions>
<option name="STORE_ONLY_LATEST_VERSION" value="false" />
<option name="CHECK_OUT_IMMEDIATELY" value="false" />
</AddOptions>
<UndocheckoutOptions>
<option name="MAKE_WRITABLE" value="false" />
<option name="REPLACE_LOCAL_COPY" value="0" />
<option name="RECURSIVE" value="false" />
</UndocheckoutOptions>
<GetOptions>
<option name="REPLACE_WRITABLE" value="0" />
<option name="MAKE_WRITABLE" value="false" />
<option name="ANSWER_NEGATIVELY" value="false" />
<option name="ANSWER_POSITIVELY" value="false" />
<option name="RECURSIVE" value="false" />
<option name="VERSION" />
</GetOptions>
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/MIT.LICENSE">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="18" selection-start="18" selection-end="18" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/json_reporter.js">
<provider selected="true" editor-type-id="text-editor">
<state line="20" column="0" selection-start="648" selection-end="648" vertical-scroll-proportion="0.15240084">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/test/bootstrap.html">
<provider selected="true" editor-type-id="text-editor">
<state line="12" column="4" selection-start="533" selection-end="533" vertical-scroll-proportion="0.23799582">
<folding />
</state>
</provider>
<provider editor-type-id="HtmlPreview">
<state />
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/example.html">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="721" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
<provider editor-type-id="HtmlPreview">
<state />
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/jasmine.css">
<provider selected="true" editor-type-id="text-editor">
<state line="17" column="36" selection-start="351" selection-end="351" vertical-scroll-proportion="0.3145083">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/example.js">
<provider selected="true" editor-type-id="text-editor">
<state line="6" column="0" selection-start="183" selection-end="183" vertical-scroll-proportion="0.11100292">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/test/bootstrap.js">
<provider selected="true" editor-type-id="text-editor">
<state line="861" column="1" selection-start="26398" selection-end="26398" vertical-scroll-proportion="0.6571146">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/jasmine.js">
<provider selected="true" editor-type-id="text-editor">
<state line="265" column="7" selection-start="5960" selection-end="5960" vertical-scroll-proportion="0.13286713">
<folding />
</state>
</provider>
</entry>
</component>
</project>

24
test/lib/jasmine.css Normal file
View File

@ -0,0 +1,24 @@
body {
font: 14px "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
padding-left: 40px;
}
h1 {
padding-top: 20px;
font-weight: bold;
font: 24px; /* "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; */
}
p {
margin-top: 5px;
padding-left: 20px;
}
p.fail {
background: url( ../images/fail-16.png ) no-repeat;
color: red;
}
p.fail_in_summary {
color: red;
}

900
test/lib/jasmine.js Executable file
View File

@ -0,0 +1,900 @@
/*
* Jasmine internal classes & objects
*/
var Jasmine = {};
Jasmine.util = {};
/** @deprecated Use Jasmine.util instead */
Jasmine.Util = Jasmine.util;
Jasmine.util.inherit = function(childClass, parentClass) {
var subclass = function() { };
subclass.prototype = parentClass.prototype;
childClass.prototype = new subclass;
};
/*
* Holds results; allows for the results array to hold another Jasmine.NestedResults
*/
Jasmine.NestedResults = function() {
this.totalCount = 0;
this.passedCount = 0;
this.failedCount = 0;
this.results = [];
};
Jasmine.NestedResults.prototype.rollupCounts = function(result) {
this.totalCount += result.totalCount;
this.passedCount += result.passedCount;
this.failedCount += result.failedCount;
};
Jasmine.NestedResults.prototype.push = function(result) {
if (result.results) {
this.rollupCounts(result);
} else {
this.totalCount++;
if (result.passed) {
this.passedCount++;
} else {
this.failedCount++;
}
}
this.results.push(result);
};
Jasmine.NestedResults.prototype.passed = function() {
return this.passedCount === this.totalCount;
};
/*
* base for Runner & Suite: allows for a queue of functions to get executed, allowing for
* any one action to complete, including asynchronous calls, before going to the next
* action.
*
**/
Jasmine.ActionCollection = function() {
this.actions = [];
this.index = 0;
this.finished = false;
this.results = new Jasmine.NestedResults();
};
Jasmine.ActionCollection.prototype.finish = function() {
if (this.finishCallback) {
this.finishCallback();
}
this.finished = true;
};
Jasmine.ActionCollection.prototype.report = function(result) {
this.results.push(result);
};
Jasmine.ActionCollection.prototype.execute = function() {
if (this.actions.length > 0) {
this.next();
}
};
Jasmine.ActionCollection.prototype.getCurrentAction = function() {
return this.actions[this.index];
};
Jasmine.ActionCollection.prototype.next = function() {
if (this.index >= this.actions.length) {
this.finish();
return;
}
var currentAction = this.getCurrentAction();
currentAction.execute(this);
if (currentAction.afterCallbacks) {
for (var i = 0; i < currentAction.afterCallbacks.length; i++) {
try {
currentAction.afterCallbacks[i]();
} catch (e) {
alert(e);
}
}
}
this.waitForDone(currentAction);
};
Jasmine.ActionCollection.prototype.waitForDone = function(action) {
var self = this;
var afterExecute = function() {
self.report(action.results);
self.index++;
self.next();
};
if (action.finished) {
afterExecute();
return;
}
var id = setInterval(function() {
if (action.finished) {
clearInterval(id);
afterExecute();
}
}, 150);
};
Jasmine.safeExecuteBeforeOrAfter = function(spec, func) {
try {
func.apply(spec);
} catch (e) {
var fail = {passed: false, message: func.typeName + '() fail: ' + Jasmine.util.formatException(e)};
spec.results.push(fail);
}
};
/*
* QueuedFunction is how ActionCollections' actions are implemented
*/
Jasmine.QueuedFunction = function(func, timeout, latchFunction, spec) {
this.func = func;
this.timeout = timeout;
this.latchFunction = latchFunction;
this.spec = spec;
this.totalTimeSpentWaitingForLatch = 0;
this.latchTimeoutIncrement = 100;
};
Jasmine.QueuedFunction.prototype.next = function() {
this.spec.finish(); // default value is to be done after one function
};
Jasmine.QueuedFunction.prototype.safeExecute = function() {
if (console) {
console.log('>> Jasmine Running ' + this.spec.suite.description + ' ' + this.spec.description + '...');
}
try {
this.func.apply(this.spec);
} catch (e) {
this.fail(e);
}
};
Jasmine.QueuedFunction.prototype.execute = function() {
var self = this;
var executeNow = function() {
self.safeExecute();
self.next();
};
var executeLater = function() {
setTimeout(executeNow, self.timeout);
};
var executeNowOrLater = function() {
var latchFunctionResult;
try {
latchFunctionResult = self.latchFunction.apply(self.spec);
} catch (e) {
self.fail(e);
self.next();
return;
}
if (latchFunctionResult) {
executeNow();
} else if (self.totalTimeSpentWaitingForLatch >= self.timeout) {
var message = 'timed out after ' + self.timeout + ' msec waiting for ' + (self.latchFunction.description || 'something to happen');
self.fail({ name: 'timeout', message: message });
self.next();
} else {
self.totalTimeSpentWaitingForLatch += self.latchTimeoutIncrement;
setTimeout(executeNowOrLater, self.latchTimeoutIncrement);
}
};
if (this.latchFunction !== undefined) {
executeNowOrLater();
} else if (this.timeout > 0) {
executeLater();
} else {
executeNow();
}
};
Jasmine.QueuedFunction.prototype.fail = function(e) {
this.spec.results.push({passed:false, message: Jasmine.util.formatException(e)});
};
/******************************************************************************
* Jasmine
******************************************************************************/
Jasmine.Env = function() {
this.currentSpec = null;
this.currentSuite = null;
this.currentRunner = null;
};
Jasmine.Env.prototype.execute = function() {
this.currentRunner.execute();
};
Jasmine.currentEnv_ = new Jasmine.Env();
/** @deprecated use Jasmine.getEnv() instead */
var jasmine = Jasmine.currentEnv_;
Jasmine.getEnv = function() {
return Jasmine.currentEnv_;
};
Jasmine.isArray_ = function(value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
Jasmine.arrayToString_ = function(array) {
var formatted_value = '';
for (var i = 0; i < array.length; i++) {
if (i > 0) {
formatted_value += ', ';
}
;
formatted_value += Jasmine.pp(array[i]);
}
return '[ ' + formatted_value + ' ]';
};
Jasmine.objectToString_ = function(obj) {
var formatted_value = '';
var first = true;
for (var property in obj) {
if (property == '__Jasmine_pp_has_traversed__') continue;
if (first) {
first = false;
} else {
formatted_value += ', ';
}
formatted_value += property;
formatted_value += ' : ';
formatted_value += Jasmine.pp(obj[property]);
}
return '{ ' + formatted_value + ' }';
};
Jasmine.ppNestLevel_ = 0;
Jasmine.pp = function(value) {
if (Jasmine.ppNestLevel_ > 40) {
// return '(Jasmine.pp nested too deeply!)';
throw new Error('Jasmine.pp nested too deeply!');
}
Jasmine.ppNestLevel_++;
try {
return Jasmine.pp_(value);
} finally {
Jasmine.ppNestLevel_--;
}
};
Jasmine.pp_ = function(value) {
if (value === undefined) {
return 'undefined';
}
if (value === null) {
return 'null';
}
if (value.navigator && value.frames && value.setTimeout) {
return '<window>';
}
if (value instanceof Jasmine.Any) return value.toString();
if (typeof value === 'string') {
return "'" + Jasmine.util.htmlEscape(value) + "'";
}
if (typeof value === 'function') {
return 'Function';
}
if (typeof value.nodeType === 'number') {
return 'HTMLNode';
}
if (value.__Jasmine_pp_has_traversed__) {
return '<circular reference: ' + (Jasmine.isArray_(value) ? 'Array' : 'Object') + '>';
}
if (Jasmine.isArray_(value) || typeof value == 'object') {
value.__Jasmine_pp_has_traversed__ = true;
var stringified = Jasmine.isArray_(value) ? Jasmine.arrayToString_(value) : Jasmine.objectToString_(value);
delete value.__Jasmine_pp_has_traversed__;
return stringified;
}
return Jasmine.util.htmlEscape(value.toString());
};
/*
* Jasmine.Matchers methods; add your own by extending Jasmine.Matchers.prototype - don't forget to write a test
*
*/
Jasmine.Matchers = function(actual, results) {
this.actual = actual;
this.passing_message = 'Passed.';
this.results = results || new Jasmine.NestedResults();
};
Jasmine.Matchers.prototype.report = function(result, failing_message) {
this.results.push({
passed: result,
message: result ? this.passing_message : failing_message
});
return result;
};
Jasmine.isDomNode = function(obj) {
return obj['nodeType'] > 0;
};
Jasmine.Any = function(expectedClass) {
this.expectedClass = expectedClass;
};
Jasmine.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;
}
return other instanceof this.expectedClass;
};
Jasmine.Any.prototype.toString = function() {
return '<Jasmine.any(' + this.expectedClass + ')>';
};
Jasmine.any = function(clazz) {
return new Jasmine.Any(clazz);
};
Jasmine.Matchers.prototype.toEqual = function(expected) {
var mismatchKeys = [];
var mismatchValues = [];
var hasKey = function(obj, keyName) {
return obj!=null && obj[keyName] !== undefined;
};
var equal = function(a, b) {
if (a == undefined || a == null) {
return (a == undefined && b == undefined);
}
if (Jasmine.isDomNode(a) && Jasmine.isDomNode(b)) {
return a === b;
}
if (typeof a === "object" && typeof b === "object") {
for (var property in b) {
if (!hasKey(a, property) && hasKey(b, property)) {
mismatchKeys.push("expected has key '" + property + "', but missing from <b>actual</b>.");
}
}
for (property in a) {
if (!hasKey(b, property) && hasKey(a, property)) {
mismatchKeys.push("<b>expected</b> missing key '" + property + "', but present in actual.");
}
}
for (property in b) {
if (!equal(a[property], b[property])) {
mismatchValues.push("'" + property + "' was<br /><br />'" + (b[property] ? Jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "'<br /><br />in expected, but was<br /><br />'" + (a[property] ? Jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "'<br /><br />in actual.<br />");
}
}
return (mismatchKeys.length == 0 && mismatchValues.length == 0);
}
if (b instanceof Jasmine.Any) {
return b.matches(a);
}
// functions are considered equivalent if their bodies are equal // todo: remove this
if (typeof a === "function" && typeof b === "function") {
return a.toString() == b.toString();
}
//Straight check
return (a === b);
};
var formatMismatches = function(name, array) {
if (array.length == 0) return '';
var errorOutput = '<br /><br />Different ' + name + ':<br />';
for (var i = 0; i < array.length; i++) {
errorOutput += array[i] + '<br />';
}
return errorOutput;
};
return this.report(equal(this.actual, expected),
'Expected<br /><br />' + Jasmine.pp(expected)
+ '<br /><br />but got<br /><br />' + Jasmine.pp(this.actual)
+ '<br />'
+ formatMismatches('Keys', mismatchKeys)
+ formatMismatches('Values', mismatchValues));
};
/** @deprecated */
Jasmine.Matchers.prototype.should_equal = Jasmine.Matchers.prototype.toEqual;
Jasmine.Matchers.prototype.toNotEqual = function(expected) {
return this.report((this.actual !== expected),
'Expected ' + Jasmine.pp(expected) + ' to not equal ' + Jasmine.pp(this.actual) + ', but it does.');
};
/** @deprecated */
Jasmine.Matchers.prototype.should_not_equal = Jasmine.Matchers.prototype.toNotEqual;
Jasmine.Matchers.prototype.toMatch = function(reg_exp) {
return this.report((new RegExp(reg_exp).test(this.actual)),
'Expected ' + this.actual + ' to match ' + reg_exp + '.');
};
/** @deprecated */
Jasmine.Matchers.prototype.should_match = Jasmine.Matchers.prototype.toMatch;
Jasmine.Matchers.prototype.toNotMatch = function(reg_exp) {
return this.report((!new RegExp(reg_exp).test(this.actual)),
'Expected ' + this.actual + ' to not match ' + reg_exp + '.');
};
/** @deprecated */
Jasmine.Matchers.prototype.should_not_match = Jasmine.Matchers.prototype.toNotMatch;
Jasmine.Matchers.prototype.toBeDefined = function() {
return this.report((this.actual !== undefined),
'Expected a value to be defined but it was undefined.');
};
/** @deprecated */
Jasmine.Matchers.prototype.should_be_defined = Jasmine.Matchers.prototype.toBeDefined;
Jasmine.Matchers.prototype.toBeNull = function() {
return this.report((this.actual === null),
'Expected a value to be null but it was not.');
};
/** @deprecated */
Jasmine.Matchers.prototype.should_be_null = Jasmine.Matchers.prototype.toBeNull;
Jasmine.Matchers.prototype.toBeTruthy = function() {
return this.report((this.actual),
'Expected a value to be truthy but it was not.');
};
/** @deprecated */
Jasmine.Matchers.prototype.should_be_truthy = Jasmine.Matchers.prototype.toBeTruthy;
Jasmine.Matchers.prototype.toBeFalsy = function() {
return this.report((!this.actual),
'Expected a value to be falsy but it was not.');
};
/** @deprecated */
Jasmine.Matchers.prototype.should_be_falsy = Jasmine.Matchers.prototype.toBeFalsy;
Jasmine.Matchers.prototype.wasCalled = function() {
if (!this.actual.isSpy) {
return this.report(false, 'Expected value to be a spy, but it was not.');
}
return this.report((this.actual.wasCalled),
'Expected spy to have been called, but it was not.');
};
/** @deprecated */
Jasmine.Matchers.prototype.was_called = Jasmine.Matchers.prototype.wasCalled;
Jasmine.Matchers.prototype.wasNotCalled = function() {
if (!this.actual.isSpy) {
return this.report(false, 'Expected value to be a spy, but it was not.');
}
return this.report((!this.actual.wasCalled),
'Expected spy to not have been called, but it was.');
};
/** @deprecated */
Jasmine.Matchers.prototype.was_not_called = Jasmine.Matchers.prototype.wasNotCalled;
Jasmine.Matchers.prototype.wasCalledWith = function() {
if (!this.wasCalled()) return false;
var argMatcher = new Jasmine.Matchers(this.actual.mostRecentCall.args, this.results);
return argMatcher.toEqual(Jasmine.util.argsToArray(arguments));
};
/** @deprecated */
Jasmine.Matchers.prototype.was_called = Jasmine.Matchers.prototype.wasCalled;
Jasmine.Matchers.prototype.toContain = function(item) {
return this.report((this.actual.indexOf(item) >= 0),
'Expected ' + Jasmine.pp(this.actual) + ' to contain ' + Jasmine.pp(item) + ', but it does not.');
};
Jasmine.Matchers.prototype.toNotContain = function(item) {
return this.report((this.actual.indexOf(item) < 0),
'Expected ' + Jasmine.pp(this.actual) + ' not to contain ' + Jasmine.pp(item) + ', but it does.');
};
Jasmine.createSpy = function() {
var spyObj = function() {
spyObj.wasCalled = true;
spyObj.callCount++;
var args = Jasmine.util.argsToArray(arguments);
spyObj.mostRecentCall = {
object: this,
args: args
};
spyObj.argsForCall.push(args);
return spyObj.plan.apply(this, arguments);
};
spyObj.isSpy = true;
spyObj.plan = function() {
};
spyObj.andCallThrough = function() {
spyObj.plan = spyObj.originalValue;
return spyObj;
};
spyObj.andReturn = function(value) {
spyObj.plan = function() {
return value;
};
return spyObj;
};
spyObj.andThrow = function(exceptionMsg) {
spyObj.plan = function() {
throw exceptionMsg;
};
return spyObj;
};
spyObj.andCallFake = function(fakeFunc) {
spyObj.plan = fakeFunc;
return spyObj;
};
spyObj.reset = function() {
spyObj.wasCalled = false;
spyObj.callCount = 0;
spyObj.argsForCall = [];
spyObj.mostRecentCall = {};
};
spyObj.reset();
return spyObj;
};
Jasmine.spyOn = function(obj, methodName) {
var spec = Jasmine.getEnv().currentSpec;
spec.after(function() {
spec.removeAllSpies();
});
if (obj == undefined) {
throw "spyOn could not find an object to spy upon";
}
if (obj[methodName] === undefined) {
throw methodName + '() method does not exist';
}
if (obj[methodName].isSpy) {
throw new Error(methodName + ' has already been spied upon');
}
var spyObj = Jasmine.createSpy();
spec.spies_.push(spyObj);
spyObj.baseObj = obj;
spyObj.methodName = methodName;
spyObj.originalValue = obj[methodName];
obj[methodName] = spyObj;
return spyObj;
};
var spyOn = Jasmine.spyOn;
/*
* Jasmine spec constructor
*/
Jasmine.Spec = function(description) {
this.suite = null;
this.description = description;
this.queue = [];
this.currentTimeout = 0;
this.currentLatchFunction = undefined;
this.finished = false;
this.afterCallbacks = [];
this.spies_ = [];
this.results = new Jasmine.NestedResults();
};
Jasmine.Spec.prototype.freezeSuite = function(suite) {
this.suite = suite;
};
/** @deprecated */
Jasmine.Spec.prototype.expects_that = function(actual) {
return new Jasmine.Matchers(actual, this.results);
};
Jasmine.Spec.prototype.waits = function(timeout) {
this.currentTimeout = timeout;
this.currentLatchFunction = undefined;
return this;
};
Jasmine.Spec.prototype.waitsFor = function(timeout, latchFunction, message) {
this.currentTimeout = timeout;
this.currentLatchFunction = latchFunction;
this.currentLatchFunction.description = message;
return this;
};
Jasmine.Spec.prototype.resetTimeout = function() {
this.currentTimeout = 0;
this.currentLatchFunction = undefined;
};
Jasmine.Spec.prototype.finishCallback = function() {
if (Jasmine.getEnv().reporter) {
Jasmine.getEnv().reporter.reportSpecResults(this.results);
}
};
Jasmine.Spec.prototype.finish = function() {
if (this.suite.afterEach) {
Jasmine.safeExecuteBeforeOrAfter(this, this.suite.afterEach);
}
this.finishCallback();
this.finished = true;
};
Jasmine.Spec.prototype.after = function(doAfter) {
this.afterCallbacks.push(doAfter);
};
Jasmine.Spec.prototype.execute = function() {
Jasmine.getEnv().currentSpec = this;
if (this.suite.beforeEach) {
Jasmine.safeExecuteBeforeOrAfter(this, this.suite.beforeEach);
}
if (this.queue[0]) {
this.queue[0].execute();
} else {
this.finish();
}
};
Jasmine.Spec.prototype.explodes = function() {
throw 'explodes function should not have been called';
};
Jasmine.Spec.prototype.spyOn = Jasmine.spyOn;
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_ = [];
};
var it = function(description, func) {
var that = new Jasmine.Spec(description);
var addToQueue = function(func) {
var currentFunction = new Jasmine.QueuedFunction(func, that.currentTimeout, that.currentLatchFunction, that);
that.queue.push(currentFunction);
if (that.queue.length > 1) {
var previousFunction = that.queue[that.queue.length - 2];
previousFunction.next = function() {
currentFunction.execute();
};
}
that.resetTimeout();
return that;
};
that.expectationResults = that.results.results;
that.runs = addToQueue;
that.freezeSuite(Jasmine.getEnv().currentSuite);
Jasmine.getEnv().currentSuite.specs.push(that);
Jasmine.getEnv().currentSpec = that;
if (func) {
addToQueue(func);
}
that.results.description = description;
return that;
};
//this mirrors the spec syntax so you can define a spec description that will not run.
var xit = function() {
return {runs: function() {
} };
};
var expect = function() {
return Jasmine.getEnv().currentSpec.expects_that.apply(Jasmine.getEnv().currentSpec, arguments);
};
var runs = function(func) {
Jasmine.getEnv().currentSpec.runs(func);
};
var waits = function(timeout) {
Jasmine.getEnv().currentSpec.waits(timeout);
};
var waitsFor = function(timeout, latchFunction, message) {
Jasmine.getEnv().currentSpec.waitsFor(timeout, latchFunction, message);
};
var beforeEach = function(beforeEach) {
beforeEach.typeName = 'beforeEach';
Jasmine.getEnv().currentSuite.beforeEach = beforeEach;
};
var afterEach = function(afterEach) {
afterEach.typeName = 'afterEach';
Jasmine.getEnv().currentSuite.afterEach = afterEach;
};
Jasmine.Description = function(description, specDefinitions) {
Jasmine.ActionCollection.call(this);
this.description = description;
this.specs = this.actions;
};
Jasmine.util.inherit(Jasmine.Description, Jasmine.ActionCollection);
var describe = function(description, spec_definitions) {
var that = new Jasmine.Description(description, spec_definitions);
Jasmine.getEnv().currentSuite = that;
Jasmine.getEnv().currentRunner.suites.push(that);
spec_definitions();
that.results.description = description;
that.specResults = that.results.results;
that.finishCallback = function() {
if (Jasmine.getEnv().reporter) {
Jasmine.getEnv().reporter.reportSuiteResults(that.results);
}
};
return that;
};
var xdescribe = function() {
return {execute: function() {
}};
};
Jasmine.Runner = function() {
Jasmine.ActionCollection.call(this);
this.suites = this.actions;
this.results.description = 'All Jasmine Suites';
};
Jasmine.util.inherit(Jasmine.Runner, Jasmine.ActionCollection);
var Runner = function() {
var that = new Jasmine.Runner();
that.finishCallback = function() {
if (Jasmine.getEnv().reporter) {
Jasmine.getEnv().reporter.reportRunnerResults(that.results);
}
};
that.suiteResults = that.results.results;
Jasmine.getEnv().currentRunner = that;
return that;
};
Jasmine.getEnv().currentRunner = Runner();
/* JasmineReporters.reporter
* Base object that will get called whenever a Spec, Suite, or Runner is done. It is up to
* descendants of this object to do something with the results (see json_reporter.js)
*/
Jasmine.Reporters = {};
Jasmine.Reporters.reporter = function(callbacks) {
var that = {
callbacks: callbacks || {},
doCallback: function(callback, results) {
if (callback) {
callback(results);
}
},
reportRunnerResults: function(results) {
that.doCallback(that.callbacks.runnerCallback, results);
},
reportSuiteResults: function(results) {
that.doCallback(that.callbacks.suiteCallback, results);
},
reportSpecResults: function(results) {
that.doCallback(that.callbacks.specCallback, results);
}
};
return that;
};
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, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
};
Jasmine.util.argsToArray = function(args) {
var arrayOfArgs = [];
for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
return arrayOfArgs;
};

62
test/lib/json_reporter.js Normal file
View File

@ -0,0 +1,62 @@
/*
* JasmineReporters.JSON --
* Basic reporter that keeps a JSON string of the most recent Spec, Suite or Runner
* result. Calling application can then do whatever it wants/needs with the string;
*/
Jasmine.Reporters.JSON = function () {
var toJSON = function(object){
return JSON.stringify(object);
};
var that = Jasmine.Reporters.reporter();
that.specJSON = '';
that.suiteJSON = '';
that.runnerJSON = '';
var saveSpecResults = function (results) {
that.specJSON = toJSON(results);
};
that.reportSpecResults = saveSpecResults;
var saveSuiteResults = function (results) {
that.suiteJSON = toJSON(results);
};
that.reportSuiteResults = saveSuiteResults;
var saveRunnerResults = function (results) {
that.runnerJSON = toJSON(results);
};
that.reportRunnerResults = saveRunnerResults;
that.toJSON = toJSON;
return that;
};
Jasmine.Reporters.domWriter = function (elementId) {
var that = {
element: document.getElementById(elementId),
write: function (text) {
if (that.element) {
that.element.innerHTML += text;
}
}
};
that.element.innerHTML = '';
return that;
};
Jasmine.Reporters.JSONtoDOM = function (elementId) {
var that = Jasmine.Reporters.JSON();
that.domWriter = Jasmine.Reporters.domWriter(elementId);
var writeRunnerResults = function (results) {
that.domWriter.write(that.toJSON(results));
};
that.reportRunnerResults = writeRunnerResults;
return that;
};

36
test/test/bootstrap.html Executable file
View File

@ -0,0 +1,36 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Tests</title>
<!--<script type="text/javascript" src="prototype-1.6.0.3.js"></script>-->
<script type="text/javascript" src="json2.js"></script>
<script type="text/javascript" src="jsUnitMockTimeout.js"></script>
<script type="text/javascript" src="../lib/jasmine.js"></script>
<script type="text/javascript" src="../lib/json_reporter.js"></script>
<link type="text/css" rel="stylesheet" href="../lib/jasmine.css"/>
<script type="text/javascript" src="bootstrap.js"></script>
</head>
<body onLoad="runTests();">
<h1>
Running all Jasmine Test Suites
</h1>
<div id="icon_wrapper">
<span id="icons"></span>
<img id="spinner" src="../images/spinner.gif" alt="" />
</div>
<div id="report">
<div id="results_summary" style="display:none;">
<h2>Summary</h2>
</div>
<div id="fails" style="display:none;">
<h2 id="fails_header">Failure Messages</h2>
<div id="fail_messages"></div>
</div>
</div>
<div style="display:none" id="json_reporter_results"></div>
<div style="display:none" id="json_reporter_results_incremental"></div>
</body>
</html>

2068
test/test/bootstrap.js vendored Executable file

File diff suppressed because it is too large Load Diff

81
test/test/jsUnitMockTimeout.js Executable file
View File

@ -0,0 +1,81 @@
// Mock setTimeout, clearTimeout
// Contributed by Pivotal Computer Systems, www.pivotalsf.com
var Clock = {
timeoutsMade: 0,
scheduledFunctions: {},
nowMillis: 0,
reset: function() {
this.scheduledFunctions = {};
this.nowMillis = 0;
this.timeoutsMade = 0;
},
tick: function(millis) {
var oldMillis = this.nowMillis;
var newMillis = oldMillis + millis;
this.runFunctionsWithinRange(oldMillis, newMillis);
this.nowMillis = newMillis;
},
runFunctionsWithinRange: function(oldMillis, nowMillis) {
var scheduledFunc;
var funcsToRun = [];
for (var timeoutKey in this.scheduledFunctions) {
scheduledFunc = this.scheduledFunctions[timeoutKey];
if (scheduledFunc != undefined &&
scheduledFunc.runAtMillis >= oldMillis &&
scheduledFunc.runAtMillis <= nowMillis) {
funcsToRun.push(scheduledFunc);
this.scheduledFunctions[timeoutKey] = undefined;
}
}
if (funcsToRun.length > 0) {
funcsToRun.sort(function(a, b) {
return a.runAtMillis - b.runAtMillis;
});
for (var i = 0; i < funcsToRun.length; ++i) {
try {
this.nowMillis = funcsToRun[i].runAtMillis;
funcsToRun[i].funcToCall();
if (funcsToRun[i].recurring) {
Clock.scheduleFunction(funcsToRun[i].timeoutKey,
funcsToRun[i].funcToCall,
funcsToRun[i].millis,
true);
}
} catch(e) {
}
}
this.runFunctionsWithinRange(oldMillis, nowMillis);
}
},
scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
Clock.scheduledFunctions[timeoutKey] = {
runAtMillis: Clock.nowMillis + millis,
funcToCall: funcToCall,
recurring: recurring,
timeoutKey: timeoutKey,
millis: millis
};
}
};
function setTimeout(funcToCall, millis) {
Clock.timeoutsMade = Clock.timeoutsMade + 1;
Clock.scheduleFunction(Clock.timeoutsMade, funcToCall, millis, false);
return Clock.timeoutsMade;
}
function setInterval(funcToCall, millis) {
Clock.timeoutsMade = Clock.timeoutsMade + 1;
Clock.scheduleFunction(Clock.timeoutsMade, funcToCall, millis, true);
return Clock.timeoutsMade;
}
function clearTimeout(timeoutKey) {
Clock.scheduledFunctions[timeoutKey] = undefined;
}
function clearInterval(timeoutKey) {
Clock.scheduledFunctions[timeoutKey] = undefined;
}

478
test/test/json2.js Normal file
View File

@ -0,0 +1,478 @@
/*
http://www.JSON.org/json2.js
2008-11-19
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 '&nbsp;'),
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 object holding the key.
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 */
/*global JSON */
/*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
*/
// 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) {
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 this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
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');
};
}
})();

57
test/test/mock-ajax.js Normal file
View File

@ -0,0 +1,57 @@
jasmine.AjaxRequests = {
requests: $A(),
activeRequest: function() {
return this.requests.last();
},
add: function(request) {
this.requests.push(request);
var spec = jasmine.getEnv().currentSpec;
spec.after(function() { jasmine.AjaxRequests.clear(); });
},
remove: function(request) {
this.requests = this.requests.without(request);
},
clear: function() {
this.requests.clear();
}
};
jasmine.AjaxRequest = Class.create(Ajax.Request, {
request: function(url) {
this.url = url;
this.method = this.options.method;
var params = Object.clone(this.options.parameters);
if (!['get', 'post'].include(this.method)) {
// simulate other verbs over post
params['_method'] = this.method;
this.method = 'post';
}
this.parameters = params;
if (params = Object.toQueryString(params)) {
// when GET, append parameters to URL
if (this.method == 'get')
this.url += (this.url.include('?') ? '&' : '?') + params;
else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
params += '&_=';
}
jasmine.AjaxRequests.add(this);
},
response: function(response) {
if (!response.status || response.status == 200 || response.status == "200") {
if (this.options.onSuccess) {this.options.onSuccess(response);}
} else {
if (this.options.onFailure) {this.options.onFailure(response);}
}
if (this.options.onComplete) {this.options.onComplete(response);}
jasmine.AjaxRequests.remove(this);
}
});

139
test/test/mock-timeout.js Executable file
View File

@ -0,0 +1,139 @@
// Mock setTimeout, clearTimeout
// Contributed by Pivotal Computer Systems, www.pivotalsf.com
jasmine.Clock = {
timeoutsMade: 0,
scheduledFunctions: {},
nowMillis: 0,
reset: function() {
jasmine.Clock.assertInstalled();
this.scheduledFunctions = {};
this.nowMillis = 0;
this.timeoutsMade = 0;
},
tick: function(millis) {
jasmine.Clock.assertInstalled();
var oldMillis = this.nowMillis;
var newMillis = oldMillis + millis;
this.runFunctionsWithinRange(oldMillis, newMillis);
this.nowMillis = newMillis;
},
runFunctionsWithinRange: function(oldMillis, nowMillis) {
var scheduledFunc;
var funcsToRun = [];
for (var timeoutKey in this.scheduledFunctions) {
scheduledFunc = this.scheduledFunctions[timeoutKey];
if (scheduledFunc != undefined &&
scheduledFunc.runAtMillis >= oldMillis &&
scheduledFunc.runAtMillis <= nowMillis) {
funcsToRun.push(scheduledFunc);
this.scheduledFunctions[timeoutKey] = undefined;
}
}
if (funcsToRun.length > 0) {
funcsToRun.sort(function(a, b) {
return a.runAtMillis - b.runAtMillis;
});
for (var i = 0; i < funcsToRun.length; ++i) {
try {
this.nowMillis = funcsToRun[i].runAtMillis;
funcsToRun[i].funcToCall();
if (funcsToRun[i].recurring) {
jasmine.Clock.scheduleFunction(funcsToRun[i].timeoutKey,
funcsToRun[i].funcToCall,
funcsToRun[i].millis,
true);
}
} catch(e) {
}
}
this.runFunctionsWithinRange(oldMillis, nowMillis);
}
},
scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
jasmine.Clock.scheduledFunctions[timeoutKey] = {
runAtMillis: jasmine.Clock.nowMillis + millis,
funcToCall: funcToCall,
recurring: recurring,
timeoutKey: timeoutKey,
millis: millis
};
},
useMock: function() {
var spec = jasmine.getEnv().currentSpec;
spec.after(jasmine.Clock.uninstallMock);
jasmine.Clock.installMock();
},
installMock: function() {
jasmine.Clock.installed = jasmine.Clock.mock;
},
uninstallMock: function() {
jasmine.Clock.assertInstalled();
jasmine.Clock.installed = jasmine.Clock.real;
},
real: {
setTimeout: window.setTimeout,
clearTimeout: window.clearTimeout,
setInterval: window.setInterval,
clearInterval: window.clearInterval
},
mock: {
setTimeout: function(funcToCall, millis) {
jasmine.Clock.timeoutsMade = jasmine.Clock.timeoutsMade + 1;
jasmine.Clock.scheduleFunction(jasmine.Clock.timeoutsMade, funcToCall, millis, false);
return jasmine.Clock.timeoutsMade;
},
setInterval: function(funcToCall, millis) {
jasmine.Clock.timeoutsMade = jasmine.Clock.timeoutsMade + 1;
jasmine.Clock.scheduleFunction(jasmine.Clock.timeoutsMade, funcToCall, millis, true);
return jasmine.Clock.timeoutsMade;
},
clearTimeout: function(timeoutKey) {
jasmine.Clock.scheduledFunctions[timeoutKey] = undefined;
},
clearInterval: function(timeoutKey) {
jasmine.Clock.scheduledFunctions[timeoutKey] = undefined;
}
},
assertInstalled: function() {
if (jasmine.Clock.installed != jasmine.Clock.mock) {
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
}
},
installed: null
};
jasmine.Clock.installed = jasmine.Clock.real;
window.setTimeout = function(funcToCall, millis) {
return jasmine.Clock.installed.setTimeout.apply(this, arguments);
};
window.setInterval = function(funcToCall, millis) {
return jasmine.Clock.installed.setInterval.apply(this, arguments);
};
window.clearTimeout = function(timeoutKey) {
return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
};
window.clearInterval = function(timeoutKey) {
return jasmine.Clock.installed.clearInterval.apply(this, arguments);
};