Compare commits
67 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 273f429754 | |||
| 90e0dbcad1 | |||
| bfec8763d7 | |||
| 7375b5279d | |||
| 909d5e9a88 | |||
| 40569149f8 | |||
| 07b60547b6 | |||
| 8ec5b9761c | |||
| 1b8a4804b7 | |||
| 65622305ae | |||
| c2341034d4 | |||
| e5503c98d8 | |||
| e0a90dd473 | |||
| 95a6085a01 | |||
| 0b02e82229 | |||
| 53305edc68 | |||
| d2fe23b52b | |||
| e26c3754b0 | |||
| 9b42df2cbf | |||
| a1ea56c1ac | |||
| 8dc4d979ff | |||
| 92e671692f | |||
| c8b38ea47a | |||
| 5821de0801 | |||
| d4683ca485 | |||
| 81aeeeedee | |||
| 2045226ba7 | |||
| 00c7d3ca29 | |||
| 73c8fef43e | |||
| 59c85355fc | |||
| e4a5d567e0 | |||
| 0c8258996e | |||
| 945b167131 | |||
| ffb69b4bde | |||
| 81748d166d | |||
| dd0e3e5cf1 | |||
| 1f50e2b2fb | |||
| 24a8bb7825 | |||
| 8fbec47739 | |||
| b38f2aa5be | |||
| 73597fc8a5 | |||
| a476f5b91c | |||
| 494d80fc66 | |||
| 4b3db52915 | |||
| 772d9ed697 | |||
| 7b1de037f8 | |||
| 3891b8afe4 | |||
| 692ae5980a | |||
| 2b9667c82e | |||
| e3585b79f0 | |||
| 1c2780d0c1 | |||
| bece09bba8 | |||
| 7c043eb5d0 | |||
| fcc1872d48 | |||
| 391c42533f | |||
| 546604fdc8 | |||
| 766eacc88b | |||
| c61c69d256 | |||
| eae0dbdc57 | |||
| abe34315a0 | |||
| 98dd13c9b2 | |||
| 2c60b0a546 | |||
| 27f165e241 | |||
| 75bb56f294 | |||
| add3e1ee7a | |||
| baf1bf10f6 | |||
| 504ba8c54d |
@@ -1,3 +1,5 @@
|
|||||||
.idea/
|
.idea
|
||||||
.svn/
|
pkg
|
||||||
.DS_Store
|
vendor
|
||||||
|
bin
|
||||||
|
!bin/jasmine
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
[submodule "pages"]
|
[submodule "jasmine"]
|
||||||
path = pages
|
path = jasmine
|
||||||
url = git@github.com:pivotal/jasmine.git
|
url = git://github.com/pivotal/jasmine.git
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#jasmine-ruby is currently designed for use with bundler 0.8.0
|
||||||
|
gem "rake", "0.8.7"
|
||||||
|
gem "jeweler", "1.4.0"
|
||||||
|
gem "gemcutter", "0.2.1"
|
||||||
|
|
||||||
|
gem "rspec", ">= 1.1.5", :only => :testing
|
||||||
|
gem "rack", ">= 1.0.0", :only => :testing
|
||||||
|
gem "thin", ">= 1.2.4", :only => :testing
|
||||||
|
gem "selenium-rc", ">=2.1.0", :only => :testing
|
||||||
|
gem "selenium-client", ">=1.2.17", :only => :testing
|
||||||
|
|
||||||
|
disable_system_gems
|
||||||
@@ -1,482 +1,37 @@
|
|||||||
[Jasmine](http://pivotal.github.com/jasmine)
|
jasmine-ruby
|
||||||
=======
|
============
|
||||||
**A JavaScript Testing Framework**
|
|
||||||
|
|
||||||
Quick Start
|
Jasmine Ruby dynamically serves HTML suites for [Jasmine](http://github.com/pivotal/jasmine)
|
||||||
----------
|
|
||||||
|
|
||||||
1. Get the latest release from the [downloads page](http://github.com/pivotal/jasmine/downloads).
|
To use:
|
||||||
2. Open `SpecRunner.html` in your favorite browser.
|
|
||||||
|
|
||||||
For running within a Ruby environment, including automated execution with Selenium, please use
|
`(sudo) gem install jasmine`
|
||||||
the [jasmine gem](http://github.com/pivotal/jasmine-gem).
|
|
||||||
|
|
||||||
### Which Release Should I Use?
|
Post-installation:
|
||||||
|
|
||||||
Please use the latest version unless you have a good reason not to. Some of this documentation may not be applicable to older versions. Please see [[Release Notes]](http://wiki.github.com/pivotal/jasmine/release-notes) for change information.
|
For Rails support, use
|
||||||
|
|
||||||
Why Another JavaScript TDD/BDD Framework?
|
`script/generate jasmine`
|
||||||
-----------
|
|
||||||
|
|
||||||
There are some great JavaScript testing frameworks out there already, so why did we write another?
|
For other projects, use
|
||||||
|
|
||||||
None of the existing frameworks quite worked the way we wanted. Many only work from within a browser. Most don't support testing asynchronous code like event callbacks. Some have syntax that's hard for JS developers or IDEs to understand.
|
`jasmine init`
|
||||||
|
|
||||||
So we decided to start from scratch.
|
After initializing a project, you may
|
||||||
|
|
||||||
Enter Jasmine
|
`rake jasmine`
|
||||||
------------
|
|
||||||
|
|
||||||
Jasmine is our dream JavaScript testing framework. It's heavily influenced by, and borrows the best parts of, ScrewUnit, JSSpec, [JSpec](http://github.com/visionmedia/jspec/tree/master), and of course RSpec.
|
to set up a server. Opening localhost:8888 in a web browser will now run your jasmine specs.
|
||||||
|
|
||||||
Jasmine was designed with a few principles in mind. We believe that a good JavaScript testing framework:
|
You may also
|
||||||
|
|
||||||
* should not be tied to any browser, framework, platform, or host language.
|
`rake jasmine:ci`
|
||||||
* should have idiomatic and unsurprising syntax.
|
|
||||||
* should work anywhere JavaScript can run, including browsers, servers, phones, etc.
|
|
||||||
* shouldn't intrude in your application's territory (e.g. by cluttering the global namespace).
|
|
||||||
* should play well with IDEs (e.g. test code should pass static analysis).
|
|
||||||
|
|
||||||
Some of our goals while writing Jasmine:
|
which will run your Jasmine suites using selenium and rspec. This task is suitable for running in continuous integration environments.
|
||||||
|
|
||||||
* it should encourage good testing practices.
|
Simple Configuration:
|
||||||
* it should integrate easily with continuous build systems.
|
|
||||||
* it should be simple to get started with.
|
|
||||||
|
|
||||||
The result is Jasmine, and we love test-driving our code with it. Enjoy.
|
Customize `spec/javascripts/support/jasmine.yaml` to enumerate the source files, stylesheets, and spec files you would like the Jasmine runner to include.
|
||||||
|
You may use dir glob strings.
|
||||||
|
|
||||||
How To
|
It is also possible to add overrides into the `spec/javascripts/support/jasmine_config.rb` file directly if you require further customization.
|
||||||
------
|
|
||||||
|
|
||||||
There is a simple 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 string and the function. The string is a description that will be helpful to you when reading a report.
|
|
||||||
|
|
||||||
it('should be a test', function () {
|
|
||||||
var foo = 0;
|
|
||||||
foo++;
|
|
||||||
});
|
|
||||||
|
|
||||||
### Expectations
|
|
||||||
|
|
||||||
Within your spec you will want to express expectations about the behavior of your application code. These are made with the `expect()` function and expectation matchers, like this:
|
|
||||||
|
|
||||||
it('should be a test', function () {
|
|
||||||
var foo = 0; // set up the world
|
|
||||||
foo++; // call your application code
|
|
||||||
|
|
||||||
expect(foo).toEqual(1); // passes because foo == 1
|
|
||||||
});
|
|
||||||
|
|
||||||
Results of the expectations are logged for later for reporting.
|
|
||||||
|
|
||||||
#### Expectation Matchers
|
|
||||||
|
|
||||||
Jasmine has several built-in matchers. Here are a few:
|
|
||||||
|
|
||||||
>`expect(x).toEqual(y);` compares objects or primitives `x` and `y` and passes if they are equivalent
|
|
||||||
>
|
|
||||||
>`expect(x).toMatch(pattern);` compares `x` to string or regular expression `pattern` and passes if they match
|
|
||||||
>
|
|
||||||
>`expect(x).toBeDefined();` passes if `x` is not `undefined`
|
|
||||||
>
|
|
||||||
>`expect(x).toBeNull();` passes if `x` is `null`
|
|
||||||
>
|
|
||||||
>`expect(x).toBeTruthy();` passes if `x` evaluates to true
|
|
||||||
>
|
|
||||||
>`expect(x).toBeFalsy();` passes if `x` evaluates to false
|
|
||||||
>
|
|
||||||
>`expect(x).toContain(y);` passes if array or string `x` contains `y`
|
|
||||||
|
|
||||||
Every matcher's criteria can be inverted by prepending `.not`:
|
|
||||||
|
|
||||||
>`expect(x).not.toEqual(y);` compares objects or primitives `x` and `y` and passes if they are *not* equivalent
|
|
||||||
|
|
||||||
#### Writing New Matchers
|
|
||||||
|
|
||||||
We've provided a small set of matchers that cover many common situations. However, we recommend that you write custom matchers when you want to assert a more specific sort of expectation. Custom matchers help to document the intent of your specs, and can help to remove code duplication in your specs.
|
|
||||||
|
|
||||||
It's extremely easy to create new matchers for your app. A matcher function receives the actual value as `this.actual`, and zero or more arguments may be passed in the function call. The function should return `true` if the actual value passes the matcher's requirements, and `false` if it does not.
|
|
||||||
|
|
||||||
Here's the definition of `toBeLessThan()`:
|
|
||||||
|
|
||||||
toBeLessThan: function(expected) {
|
|
||||||
return this.actual < expected;
|
|
||||||
};
|
|
||||||
|
|
||||||
To add the matcher to your suite, call `this.addMatchers()` from within a `before` or `it` block. Call it with an object mapping matcher name to function:
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
this.addMatchers({
|
|
||||||
toBeVisible: function() { return this.actual.isVisible(); }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
### 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 Suite 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. Additionally, specs within a suite share a functional scope. So you may declare variables inside a describe block and they are accessible from within your specs. For example:
|
|
||||||
|
|
||||||
describe('A suite with some variables', function () {
|
|
||||||
var bar = 0
|
|
||||||
|
|
||||||
it('has a test', function () {
|
|
||||||
bar++;
|
|
||||||
expect(bar).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('has another test', function () {
|
|
||||||
bar++;
|
|
||||||
expect(bar).toEqual(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
#### beforeEach
|
|
||||||
|
|
||||||
A suite can have a beforeEach declaration. It takes a function that is run before each spec. For example:
|
|
||||||
|
|
||||||
describe('some suite', function () {
|
|
||||||
|
|
||||||
var suiteWideFoo;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
suiteWideFoo = 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should equal bar', function () {
|
|
||||||
expect(suiteWideFoo).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
A runner can also have beforeEach declarations. Runner beforeEach functions are executed before every spec in all suites, and execute BEFORE suite beforeEach functions. For example:
|
|
||||||
|
|
||||||
var runnerWideFoo = [];
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
runnerWideFoo.push('runner');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('some suite', function () {
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
runnerWideFoo.push('suite');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should equal bar', function () {
|
|
||||||
expect(runnerWideFoo).toEqual(['runner', 'suite']);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
#### afterEach
|
|
||||||
|
|
||||||
Similarly, there is an afterEach declaration. It takes a function that is run after each spec. For example:
|
|
||||||
|
|
||||||
describe('some suite', function () {
|
|
||||||
|
|
||||||
var suiteWideFoo;
|
|
||||||
afterEach(function () {
|
|
||||||
suiteWideFoo = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should equal 1', function () {
|
|
||||||
expect(suiteWideFoo).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should equal 0 after', function () {
|
|
||||||
expect(suiteWideFoo).toEqual(0);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
A runner can also have an afterEach declarations. Runner afterEach functions are executed after every spec in all suites, and execute AFTER suite afterEach functions. For example:
|
|
||||||
|
|
||||||
var runnerWideFoo = [];
|
|
||||||
|
|
||||||
afterEach(function () {
|
|
||||||
runnerWideFoo.push('runner');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('some suite', function () {
|
|
||||||
|
|
||||||
afterEach(function () {
|
|
||||||
runnerWideFoo.push('suite');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be empty', function () {
|
|
||||||
expect(runnerWideFoo).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be populated after', function () {
|
|
||||||
expect(runnerWideFoo).toEqual(['suite', 'runner']);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
### Single-spec After functions
|
|
||||||
|
|
||||||
A spec may ask Jasmine to execute some code after the spec has finished running; the code will run whether the spec finishes successfully or not. Multiple after functions may be given.
|
|
||||||
|
|
||||||
describe('some suite', function () {
|
|
||||||
it(function () {
|
|
||||||
var originalTitle = window.title;
|
|
||||||
this.after(function() { window.title = originalTitle; });
|
|
||||||
MyWindow.setTitle("new value");
|
|
||||||
expect(window.title).toEqual("new value");
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
### Nested Describes
|
|
||||||
Jasmine supports nested describes. An example:
|
|
||||||
|
|
||||||
describe('some suite', function () {
|
|
||||||
|
|
||||||
var suiteWideFoo;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
suiteWideFoo = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('some nested suite', function() {
|
|
||||||
var nestedSuiteBar;
|
|
||||||
beforeEach(function() {
|
|
||||||
nestedSuiteBar=1;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('nested expectation', function () {
|
|
||||||
expect(suiteWideFoo).toEqual(0);
|
|
||||||
expect(nestedSuiteBar).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
it('top-level describe', function () {
|
|
||||||
expect(suiteWideFoo).toEqual(0);
|
|
||||||
expect(nestedSuiteBar).toEqual(undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
### Spies
|
|
||||||
|
|
||||||
Jasmine integrates 'spies' that permit many spying, mocking, and faking behaviors.
|
|
||||||
|
|
||||||
Here are a few examples:
|
|
||||||
|
|
||||||
var Klass = function () {
|
|
||||||
};
|
|
||||||
|
|
||||||
var Klass.prototype.method = function (arg) {
|
|
||||||
return arg;
|
|
||||||
};
|
|
||||||
|
|
||||||
var Klass.prototype.methodWithCallback = function (callback) {
|
|
||||||
return callback('foo');
|
|
||||||
};
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
it('should spy on Klass#method') {
|
|
||||||
spyOn(Klass, 'method');
|
|
||||||
Klass.method('foo argument');
|
|
||||||
|
|
||||||
expect(Klass.method).toHaveBeenCalledWith('foo argument');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should spy on Klass#methodWithCallback') {
|
|
||||||
var callback = Jasmine.createSpy();
|
|
||||||
Klass.methodWithCallback(callback);
|
|
||||||
|
|
||||||
expect(callback).toHaveBeenCalledWith('foo');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
Spies can be very useful for testing AJAX or other asynchronous behaviors that take callbacks by faking the method firing an async call.
|
|
||||||
|
|
||||||
var Klass = function () {
|
|
||||||
};
|
|
||||||
|
|
||||||
var Klass.prototype.asyncMethod = function (callback) {
|
|
||||||
someAsyncCall(callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
it('should test async call') {
|
|
||||||
spyOn(Klass, 'asyncMethod');
|
|
||||||
var callback = Jasmine.createSpy();
|
|
||||||
|
|
||||||
Klass.asyncMethod(callback);
|
|
||||||
expect(callback).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
var someResponseData = 'foo';
|
|
||||||
Klass.asyncMethod.mostRecentCall.args[0](someResponseData);
|
|
||||||
expect(callback).toHaveBeenCalledWith(someResponseData);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
There are spy-specfic matchers that are very handy.
|
|
||||||
|
|
||||||
`expect(x).toHaveBeenCalled()` passes if `x` is a spy and was called
|
|
||||||
|
|
||||||
`expect(x).toHaveBeenCalledWith(arguments)` passes if `x` is a spy and was called with the specified arguments
|
|
||||||
|
|
||||||
`expect(x).not.toHaveBeenCalled()` passes if `x` is a spy and was not called
|
|
||||||
|
|
||||||
`expect(x).not.toHaveBeenCalledWith(arguments)` passes if `x` is a spy and was not called with the specified arguments
|
|
||||||
|
|
||||||
The old matchers `wasCalled`, `wasNotCalled`, `wasCalledWith`, and `wasNotCalledWith` have been deprecated and will be removed in a future release. Please change your specs to use `toHaveBeenCalled`, `not.toHaveBeenCalled`, `toHaveBeenCalledWith`, and `not.toHaveBeenCalledWith` respectively.
|
|
||||||
|
|
||||||
Spies can be trained to respond in a variety of ways when invoked:
|
|
||||||
|
|
||||||
`spyOn(x, 'method').andCallThrough()`: spies on AND calls the original function spied on
|
|
||||||
|
|
||||||
`spyOn(x, 'method').andReturn(arguments)`: returns passed arguments when spy is called
|
|
||||||
|
|
||||||
`spyOn(x, 'method').andThrow(exception)`: throws passed exception when spy is called
|
|
||||||
|
|
||||||
`spyOn(x, 'method').andCallFake(function)`: calls passed function when spy is called
|
|
||||||
|
|
||||||
Spies have some useful properties:
|
|
||||||
|
|
||||||
`callCount`: returns number of times spy was called
|
|
||||||
|
|
||||||
`mostRecentCall.args`: returns argument array from last call to spy.
|
|
||||||
|
|
||||||
`argsForCall[i]` returns arguments array for call `i` to spy.
|
|
||||||
|
|
||||||
Spies are automatically removed after each spec. They may be set in the beforeEach function.
|
|
||||||
|
|
||||||
### Disabling Tests & Suites
|
|
||||||
|
|
||||||
Specs may be disabled by calling `xit()` instead of `it()`. Suites may be disabled by calling `xdescribe()` instead of `describe()`. A simple find/replace in your editor of choice will allow you to run a subset of your specs.
|
|
||||||
|
|
||||||
### Asynchronous Specs
|
|
||||||
|
|
||||||
You may be thinking, "That's all very nice, but what's this about asynchronous tests?"
|
|
||||||
|
|
||||||
Well, say you need to make a call that is asynchronous - an AJAX API, event callback, 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 with `runs()` and `waits()` blocks.
|
|
||||||
|
|
||||||
`runs()` blocks by themselves simply run as if they were called directly. The following snippets of code should provide similar results:
|
|
||||||
|
|
||||||
it('should be a test', function () {
|
|
||||||
var foo = 0
|
|
||||||
foo++;
|
|
||||||
|
|
||||||
expect(foo).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
and
|
|
||||||
|
|
||||||
it('should be a test', function () {
|
|
||||||
runs( function () {
|
|
||||||
var foo = 0
|
|
||||||
foo++;
|
|
||||||
|
|
||||||
expect(foo).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
multiple `runs()` blocks in a spec will run serially. For example,
|
|
||||||
|
|
||||||
it('should be a test', function () {
|
|
||||||
runs( function () {
|
|
||||||
var foo = 0
|
|
||||||
foo++;
|
|
||||||
|
|
||||||
expect(foo).toEqual(1);
|
|
||||||
});
|
|
||||||
runs( function () {
|
|
||||||
var bar = 0
|
|
||||||
bar++;
|
|
||||||
|
|
||||||
expect(bar).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
`runs()` blocks share functional scope -- `this` properties will be common to all blocks, but declared `var`'s will not!
|
|
||||||
|
|
||||||
it('should be a test', function () {
|
|
||||||
runs( function () {
|
|
||||||
this.foo = 0
|
|
||||||
this.foo++;
|
|
||||||
var bar = 0;
|
|
||||||
bar++;
|
|
||||||
|
|
||||||
expect(this.foo).toEqual(1);
|
|
||||||
expect(bar).toEqual(1);
|
|
||||||
});
|
|
||||||
runs( function () {
|
|
||||||
this.foo++;
|
|
||||||
var bar = 0
|
|
||||||
bar++;
|
|
||||||
|
|
||||||
expect(foo).toEqual(2);
|
|
||||||
expect(bar).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
`runs()` blocks exist so you can test asynchronous processes. The function `waits()` works with `runs()` to provide a naive
|
|
||||||
timeout before the next block is run. You supply a time to wait before the next `runs()` function is executed. For example:
|
|
||||||
|
|
||||||
it('should be a test', function () {
|
|
||||||
runs(function () {
|
|
||||||
this.foo = 0;
|
|
||||||
var that = this;
|
|
||||||
setTimeout(function () {
|
|
||||||
that.foo++;
|
|
||||||
}, 250);
|
|
||||||
});
|
|
||||||
|
|
||||||
runs(function () {
|
|
||||||
this.expects(this.foo).toEqual(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
waits(500);
|
|
||||||
|
|
||||||
runs(function () {
|
|
||||||
this.expects(this.foo).toEqual(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`.
|
|
||||||
|
|
||||||
## Support
|
|
||||||
We now have a Google Group for support & discussion.
|
|
||||||
|
|
||||||
* Discussion: [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js)
|
|
||||||
* Group email: [jasmine-js@googlegroups.com](jasmine-js@googlegroups.com)
|
|
||||||
* Current build status of Jasmine is visible at [ci.pivotallabs.com](http://ci.pivotallabs.com)
|
|
||||||
* Pivotal Tracker project: [http://www.pivotaltracker.com/projects/10606](http://www.pivotaltracker.com/projects/10606)
|
|
||||||
* Twitter: [@JasmineBDD](http://twitter.com/JasmineBDD)
|
|
||||||
|
|
||||||
## Maintainers
|
|
||||||
* [Davis W. Frank](mailto:dwfrank@pivotallabs.com), Pivotal Labs
|
|
||||||
* [Rajan Agaskar](mailto:rajan@pivotallabs.com), Pivotal Labs
|
|
||||||
* [Christian Williams](mailto:xian@pivotallabs.com), Pivotal Labs
|
|
||||||
|
|
||||||
## Developers
|
|
||||||
We welcome your contributions! Jasmine is currently maintained by Davis Frank ([infews](http://github.com/infews)), Rajan Agaskar ([ragaskar](http://github.com/ragaskar)), and Christian Williams ([Xian](http://github.com/Xian)). You can help us by removing all other recipients from your pull request.
|
|
||||||
|
|
||||||
## 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
|
|
||||||
* Huge contributions have been made by [Adam Abrons](mailto:adam@pivotallabs.com), [Lee Byrd](mailto:lee@pivotallabs.com), [Erik Hanson](mailto:erik@pivotallabs.com), [Carl Jackson](mailto:carl@pivotallabs.com), and many other Pivots.
|
|
||||||
|
|||||||
@@ -1,176 +1,66 @@
|
|||||||
def jasmine_sources
|
require "#{File.dirname(__FILE__)}/vendor/gems/environment"
|
||||||
sources = ["src/base.js", "src/util.js", "src/Env.js", "src/Reporter.js", "src/Block.js"]
|
Bundler.require_env :rake
|
||||||
sources += Dir.glob('src/*.js').reject { |f| f == 'src/base.js' || sources.include?(f) }.sort
|
|
||||||
sources
|
|
||||||
end
|
|
||||||
|
|
||||||
def jasmine_html_sources
|
$LOAD_PATH.unshift File.expand_path("#{File.dirname(__FILE__)}/lib")
|
||||||
["src/html/TrivialReporter.js"]
|
|
||||||
end
|
|
||||||
|
|
||||||
def jasmine_version
|
require 'spec'
|
||||||
"#{version_hash['major']}.#{version_hash['minor']}.#{version_hash['build']}"
|
require 'spec/rake/spectask'
|
||||||
end
|
|
||||||
|
|
||||||
def version_hash
|
desc "Run all examples"
|
||||||
require 'json'
|
Spec::Rake::SpecTask.new('spec') do |t|
|
||||||
@version ||= JSON.parse(File.new("src/version.json").read);
|
t.spec_files = FileList['spec/**/*.rb']
|
||||||
end
|
|
||||||
|
|
||||||
task :default => 'jasmine:dist'
|
|
||||||
|
|
||||||
def substitute_jasmine_version(filename)
|
|
||||||
contents = File.read(filename)
|
|
||||||
contents = contents.gsub(/##JASMINE_VERSION##/, (jasmine_version))
|
|
||||||
File.open(filename, 'w') { |f| f.write(contents) }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
namespace :jasmine do
|
namespace :jasmine do
|
||||||
|
# require 'jasmine'
|
||||||
|
require 'spec/jasmine_self_test_config'
|
||||||
|
|
||||||
desc 'Prepares for distribution'
|
# desc "Run continuous integration tests"
|
||||||
task :dist => ['jasmine:build', 'jasmine:doc', 'jasmine:build_example_project', 'jasmine:fill_index_downloads']
|
# require "spec"
|
||||||
|
# require 'spec/rake/spectask'
|
||||||
|
# Spec::Rake::SpecTask.new(:ci) do |t|
|
||||||
|
# t.spec_opts = ["--color", "--format", "specdoc"]
|
||||||
|
# t.verbose = true
|
||||||
|
# t.spec_files = [JasmineHelper.meta_spec_path]
|
||||||
|
# end
|
||||||
|
|
||||||
desc 'Check jasmine sources for coding problems'
|
task :server do
|
||||||
task :lint do
|
puts "your tests are here:"
|
||||||
passed = true
|
puts " http://localhost:8888/run.html"
|
||||||
jasmine_sources.each do |src|
|
|
||||||
lines = File.read(src).split(/\n/)
|
|
||||||
lines.each_index do |i|
|
|
||||||
line = lines[i]
|
|
||||||
undefineds = line.scan(/.?undefined/)
|
|
||||||
if undefineds.include?(" undefined") || undefineds.include?("\tundefined")
|
|
||||||
puts "Dangerous undefined at #{src}:#{i}:\n > #{line}"
|
|
||||||
passed = false
|
|
||||||
end
|
|
||||||
|
|
||||||
if line.scan(/window/).length > 0
|
JasmineSelfTestConfig.new.start_server
|
||||||
puts "Dangerous window at #{src}:#{i}:\n > #{line}"
|
|
||||||
passed = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
unless passed
|
|
||||||
puts "Lint failed!"
|
|
||||||
exit 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'Builds lib/jasmine from source'
|
|
||||||
task :build => :lint do
|
|
||||||
puts 'Building Jasmine from source'
|
|
||||||
|
|
||||||
sources = jasmine_sources
|
|
||||||
version = version_hash
|
|
||||||
|
|
||||||
old_jasmine_files = Dir.glob('lib/jasmine*.js')
|
|
||||||
old_jasmine_files.each { |file| File.delete(file) }
|
|
||||||
|
|
||||||
File.open("lib/jasmine.js", 'w') do |jasmine|
|
|
||||||
sources.each do |source_filename|
|
|
||||||
jasmine.puts(File.read(source_filename))
|
|
||||||
end
|
|
||||||
|
|
||||||
jasmine.puts %{
|
|
||||||
jasmine.version_= {
|
|
||||||
"major": #{version['major']},
|
|
||||||
"minor": #{version['minor']},
|
|
||||||
"build": #{version['build']},
|
|
||||||
"revision": #{Time.now.to_i}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
File.open("lib/jasmine-html.js", 'w') do |jasmine_html|
|
|
||||||
jasmine_html_sources.each do |source_filename|
|
|
||||||
jasmine_html.puts(File.read(source_filename))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
FileUtils.cp("src/html/jasmine.css", "lib/jasmine.css")
|
|
||||||
end
|
|
||||||
|
|
||||||
task :need_pages_submodule do
|
|
||||||
unless File.exists?('pages/index.html')
|
|
||||||
raise "Jasmine pages submodule isn't present. Run git submodule update --init"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Build jasmine documentation"
|
|
||||||
task :doc => :need_pages_submodule do
|
|
||||||
puts 'Creating Jasmine Documentation'
|
|
||||||
require 'rubygems'
|
|
||||||
#sudo gem install ragaskar-jsdoc_helper
|
|
||||||
require 'jsdoc_helper'
|
|
||||||
|
|
||||||
FileUtils.rm_r "pages/jsdoc", :force => true
|
|
||||||
|
|
||||||
JsdocHelper::Rake::Task.new(:lambda_jsdoc) do |t|
|
|
||||||
t[:files] = jasmine_sources << jasmine_html_sources
|
|
||||||
t[:options] = "-a"
|
|
||||||
t[:out] = "pages/jsdoc"
|
|
||||||
end
|
|
||||||
Rake::Task[:lambda_jsdoc].invoke
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "Build example project"
|
|
||||||
task :build_example_project => :need_pages_submodule do
|
|
||||||
require 'tmpdir'
|
|
||||||
|
|
||||||
temp_dir = File.join(Dir.tmpdir, 'jasmine-standalone-project')
|
|
||||||
puts "Building Example Project in #{temp_dir}"
|
|
||||||
FileUtils.rm_r temp_dir if File.exists?(temp_dir)
|
|
||||||
Dir.mkdir(temp_dir)
|
|
||||||
|
|
||||||
root = File.expand_path(File.dirname(__FILE__))
|
|
||||||
FileUtils.cp_r File.join(root, 'example/.'), File.join(temp_dir)
|
|
||||||
substitute_jasmine_version(File.join(temp_dir, "SpecRunner.html"))
|
|
||||||
|
|
||||||
lib_dir = File.join(temp_dir, "lib/jasmine-#{jasmine_version}")
|
|
||||||
FileUtils.mkdir_p(lib_dir)
|
|
||||||
{
|
|
||||||
"lib/jasmine.js" => "jasmine.js",
|
|
||||||
"lib/jasmine-html.js" => "jasmine-html.js",
|
|
||||||
"src/html/jasmine.css" => "jasmine.css"
|
|
||||||
}.each_pair do |src, dest|
|
|
||||||
FileUtils.cp(File.join(root, src), File.join(lib_dir, dest))
|
|
||||||
end
|
|
||||||
|
|
||||||
dist_dir = File.join(root, 'pages/downloads')
|
|
||||||
zip_file_name = File.join(dist_dir, "jasmine-standalone-#{jasmine_version}.zip")
|
|
||||||
puts "Zipping Example Project and moving to #{zip_file_name}"
|
|
||||||
FileUtils.mkdir(dist_dir) unless File.exist?(dist_dir)
|
|
||||||
if File.exist?(zip_file_name)
|
|
||||||
puts "WARNING!!! #{zip_file_name} already exists!"
|
|
||||||
FileUtils.rm(zip_file_name)
|
|
||||||
end
|
|
||||||
exec "cd #{temp_dir} && zip -r #{zip_file_name} . -x .[a-zA-Z0-9]*"
|
|
||||||
end
|
|
||||||
|
|
||||||
task :fill_index_downloads do
|
|
||||||
require 'digest/sha1'
|
|
||||||
|
|
||||||
download_html = "<!-- START_DOWNLOADS -->\n"
|
|
||||||
download_html += "<table>\n<tr><th/><th>Version</th><th>Size</th><th>Date</th><th>SHA1</th></tr>\n"
|
|
||||||
Dir.glob('pages/downloads/*.zip').sort.reverse.each do |f|
|
|
||||||
sha1 = Digest::SHA1.hexdigest File.read(f)
|
|
||||||
|
|
||||||
fn = f.sub(/^pages\//, '')
|
|
||||||
version = /jasmine-standalone-(.*).zip/.match(f)[1]
|
|
||||||
download_html += "<td><a href='#{fn}'>#{fn.sub(/downloads\//, '')}</a></td>"
|
|
||||||
download_html += "<td>#{version}</td>\n"
|
|
||||||
download_html += "<td>#{File.size(f) / 1024}k</td>\n"
|
|
||||||
download_html += "<td>#{File.mtime(f).strftime("%Y/%m/%d %H:%M:%S")}</td>\n"
|
|
||||||
download_html += "<td>#{sha1}</td>\n"
|
|
||||||
end
|
|
||||||
download_html += "</table>\n<!-- END_DOWNLOADS -->"
|
|
||||||
|
|
||||||
index_page = File.read('pages/index.html')
|
|
||||||
matcher = /<!-- START_DOWNLOADS -->.*<!-- END_DOWNLOADS -->/m
|
|
||||||
index_page = index_page.sub(matcher, download_html)
|
|
||||||
File.open('pages/index.html', 'w') {|f| f.write(index_page)}
|
|
||||||
puts "rewrote that file"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
task :jasmine => ['jasmine:dist']
|
desc "Run specs via server"
|
||||||
|
task :jasmine => ['jasmine:server']
|
||||||
|
|
||||||
|
|
||||||
|
namespace :jeweler do
|
||||||
|
|
||||||
|
unless File.exists?('jasmine/lib')
|
||||||
|
raise "Jasmine submodule isn't present. Run git submodule update --init"
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
require 'jeweler'
|
||||||
|
require 'rake'
|
||||||
|
Jeweler::Tasks.new do |gemspec|
|
||||||
|
gemspec.name = "jasmine"
|
||||||
|
gemspec.summary = "Jasmine Ruby Runner"
|
||||||
|
gemspec.description = "Javascript BDD test framework"
|
||||||
|
gemspec.email = "ragaskar@gmail.com"
|
||||||
|
gemspec.homepage = "http://github.com/pivotal/jasmine-ruby"
|
||||||
|
gemspec.authors = ["Rajan Agaskar", "Christian Williams"]
|
||||||
|
gemspec.executables = ["jasmine"]
|
||||||
|
gemspec.files = FileList.new('generators/**/**', 'lib/**/**', 'jasmine/lib/**', 'jasmine/contrib/ruby/**', 'tasks/**', 'templates/**')
|
||||||
|
gemspec.add_dependency('rspec', '>= 1.1.5')
|
||||||
|
gemspec.add_dependency('json', '>= 1.1.9')
|
||||||
|
gemspec.add_dependency('rack', '>= 1.0.0')
|
||||||
|
gemspec.add_dependency('thin', '>= 1.2.4')
|
||||||
|
gemspec.add_dependency('selenium-rc', '>=2.1.0')
|
||||||
|
gemspec.add_dependency('selenium-client', '>=1.2.17')
|
||||||
|
end
|
||||||
|
Jeweler::GemcutterTasks.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
:patch: 5
|
||||||
|
:major: 0
|
||||||
|
:build:
|
||||||
|
:minor: 4
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
require 'rubygems'
|
||||||
|
require 'rake'
|
||||||
|
|
||||||
|
def cwd
|
||||||
|
File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
||||||
|
end
|
||||||
|
|
||||||
|
def expand(*paths)
|
||||||
|
File.expand_path(File.join(*paths))
|
||||||
|
end
|
||||||
|
|
||||||
|
def template_path(filepath)
|
||||||
|
expand(cwd, File.join("generators/jasmine/templates", filepath))
|
||||||
|
end
|
||||||
|
|
||||||
|
def dest_path(filepath)
|
||||||
|
expand(Dir.pwd, filepath)
|
||||||
|
end
|
||||||
|
|
||||||
|
def copy_unless_exists(relative_path, dest_path = nil)
|
||||||
|
unless File.exist?(dest_path(relative_path))
|
||||||
|
File.copy(template_path(relative_path), dest_path(dest_path || relative_path))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if ARGV[0] == 'init'
|
||||||
|
require 'ftools'
|
||||||
|
File.makedirs('spec/javascripts')
|
||||||
|
File.makedirs('spec/javascripts/support')
|
||||||
|
|
||||||
|
copy_unless_exists('spec/javascripts/SpecHelper.js')
|
||||||
|
copy_unless_exists('spec/javascripts/ExampleSpec.js')
|
||||||
|
copy_unless_exists('spec/javascripts/support/jasmine_config.rb')
|
||||||
|
copy_unless_exists('spec/javascripts/support/jasmine_runner.rb')
|
||||||
|
|
||||||
|
rails_tasks_dir = dest_path('lib/tasks')
|
||||||
|
if File.exist?(rails_tasks_dir)
|
||||||
|
copy_unless_exists('lib/tasks/jasmine.rake')
|
||||||
|
copy_unless_exists('spec/javascripts/support/jasmine-rails.yml', 'spec/javascripts/support/jasmine.yml')
|
||||||
|
else
|
||||||
|
copy_unless_exists('spec/javascripts/support/jasmine.yml')
|
||||||
|
write_mode = 'w'
|
||||||
|
if File.exist?(dest_path('Rakefile'))
|
||||||
|
load dest_path('Rakefile')
|
||||||
|
write_mode = 'a'
|
||||||
|
end
|
||||||
|
unless Rake::Task.task_defined?('jasmine')
|
||||||
|
File.open(dest_path('Rakefile'), write_mode) do |f|
|
||||||
|
f.write(File.read(template_path('lib/tasks/jasmine.rake')))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
File.open(template_path('INSTALL'), 'r').each_line do |line|
|
||||||
|
puts line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# Project-specific configuration for CruiseControl.rb
|
|
||||||
Project.configure do |project|
|
|
||||||
|
|
||||||
# Send email notifications about broken and fixed builds to email1@your.site, email2@your.site (default: send to nobody)
|
|
||||||
# project.email_notifier.emails = ['email1@your.site', 'email2@your.site']
|
|
||||||
|
|
||||||
# Set email 'from' field to john@doe.com:
|
|
||||||
# project.email_notifier.from = 'john@doe.com'
|
|
||||||
|
|
||||||
# Build the project by invoking rake task 'custom'
|
|
||||||
project.rake_task = 'jasmine:test:ci:saucelabs'
|
|
||||||
|
|
||||||
# Build the project by invoking shell script "build_my_app.sh". Keep in mind that when the script is invoked,
|
|
||||||
# current working directory is <em>[cruise data]</em>/projects/your_project/work, so if you do not keep build_my_app.sh
|
|
||||||
# in version control, it should be '../build_my_app.sh' instead
|
|
||||||
#project.build_command = 'cp ../saucelabs.yml .'
|
|
||||||
|
|
||||||
# Ping Subversion for new revisions every 5 minutes (default: 30 seconds)
|
|
||||||
# project.scheduler.polling_interval = 5.minutes
|
|
||||||
|
|
||||||
end
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/html4/loose.dtd">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Jasmine Test Runner</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="lib/jasmine-##JASMINE_VERSION##/jasmine.css">
|
|
||||||
<script type="text/javascript" src="lib/jasmine-##JASMINE_VERSION##/jasmine.js"></script>
|
|
||||||
<script type="text/javascript" src="lib/jasmine-##JASMINE_VERSION##/jasmine-html.js"></script>
|
|
||||||
|
|
||||||
<!-- include source files here... -->
|
|
||||||
<script type="text/javascript" src="src/Player.js"></script>
|
|
||||||
<script type="text/javascript" src="src/Song.js"></script>
|
|
||||||
|
|
||||||
<!-- include spec files here... -->
|
|
||||||
<script type="text/javascript" src="spec/SpecHelper.js"></script>
|
|
||||||
<script type="text/javascript" src="spec/PlayerSpec.js"></script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script type="text/javascript">
|
|
||||||
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
|
|
||||||
jasmine.getEnv().execute();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
describe("Player", function() {
|
|
||||||
var player;
|
|
||||||
var song;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
player = new Player();
|
|
||||||
song = new Song();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should be able to play a Song", function() {
|
|
||||||
player.play(song);
|
|
||||||
expect(player.currentlyPlayingSong).toEqual(song);
|
|
||||||
|
|
||||||
//demonstrates use of custom matcher
|
|
||||||
expect(player).toBePlaying(song);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when song has been paused", function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
player.play(song);
|
|
||||||
player.pause();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should indicate that the song is currently paused", function() {
|
|
||||||
expect(player.isPlaying).toBeFalsy();
|
|
||||||
|
|
||||||
// demonstrates use of 'not' with a custom matcher
|
|
||||||
expect(player).not.toBePlaying(song);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should be possible to resume", function() {
|
|
||||||
player.resume();
|
|
||||||
expect(player.isPlaying).toBeTruthy();
|
|
||||||
expect(player.currentlyPlayingSong).toEqual(song);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// demonstrates use of spies to intercept and test method calls
|
|
||||||
it("tells the current song if the user has made it a favorite", function() {
|
|
||||||
spyOn(song, 'persistFavoriteStatus');
|
|
||||||
|
|
||||||
player.play(song);
|
|
||||||
player.makeFavorite();
|
|
||||||
|
|
||||||
expect(song.persistFavoriteStatus).toHaveBeenCalledWith(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
//demonstrates use of expected exceptions
|
|
||||||
describe("#resume", function() {
|
|
||||||
it("should throw an exception if song is already playing", function() {
|
|
||||||
player.play(song);
|
|
||||||
|
|
||||||
expect(function() {
|
|
||||||
player.resume();
|
|
||||||
}).toThrow("song is already playing");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
beforeEach(function() {
|
|
||||||
this.addMatchers({
|
|
||||||
toBePlaying: function(expectedSong) {
|
|
||||||
var player = this.actual;
|
|
||||||
return player.currentlyPlayingSong === expectedSong
|
|
||||||
&& player.isPlaying;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
function Player() {
|
|
||||||
}
|
|
||||||
Player.prototype.play = function(song) {
|
|
||||||
this.currentlyPlayingSong = song;
|
|
||||||
this.isPlaying = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
Player.prototype.pause = function() {
|
|
||||||
this.isPlaying = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
Player.prototype.resume = function() {
|
|
||||||
if (this.isPlaying) {
|
|
||||||
throw new Error("song is already playing");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isPlaying = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
Player.prototype.makeFavorite = function() {
|
|
||||||
this.currentlyPlayingSong.persistFavoriteStatus(true);
|
|
||||||
};
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
function Song() {
|
|
||||||
}
|
|
||||||
|
|
||||||
Song.prototype.persistFavoriteStatus = function(value) {
|
|
||||||
// something complicated
|
|
||||||
throw new Error("not yet implemented");
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
class JasmineGenerator < Rails::Generator::Base
|
||||||
|
def manifest
|
||||||
|
record do |m|
|
||||||
|
|
||||||
|
m.directory "spec/javascripts"
|
||||||
|
m.file "spec/javascripts/SpecHelper.js", "spec/javascripts/SpecHelper.js"
|
||||||
|
m.file "spec/javascripts/ExampleSpec.js", "spec/javascripts/ExampleSpec.js"
|
||||||
|
|
||||||
|
m.directory "spec/javascripts/support"
|
||||||
|
m.file "spec/javascripts/support/jasmine_config.rb", "spec/javascripts/support/jasmine_config.rb"
|
||||||
|
m.file "spec/javascripts/support/jasmine_runner.rb", "spec/javascripts/support/jasmine_runner.rb"
|
||||||
|
m.file "spec/javascripts/support/jasmine-rails.yml", "spec/javascripts/support/jasmine.yml"
|
||||||
|
|
||||||
|
m.directory "lib/tasks"
|
||||||
|
m.file "lib/tasks/jasmine.rake", "lib/tasks/jasmine.rake"
|
||||||
|
|
||||||
|
m.readme "INSTALL"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def file_name
|
||||||
|
"create_blog"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
Jasmine has been installed with example specs.
|
||||||
|
|
||||||
|
To run the server:
|
||||||
|
|
||||||
|
rake jasmine
|
||||||
|
|
||||||
|
To run the automated CI task with Selenium:
|
||||||
|
|
||||||
|
rake jasmine:ci
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
namespace :jasmine do
|
||||||
|
require 'jasmine'
|
||||||
|
|
||||||
|
desc "Run continuous integration tests"
|
||||||
|
require "spec"
|
||||||
|
require 'spec/rake/spectask'
|
||||||
|
Spec::Rake::SpecTask.new(:ci) do |t|
|
||||||
|
t.spec_opts = ["--color", "--format", "specdoc"]
|
||||||
|
t.verbose = true
|
||||||
|
t.spec_files = ['spec/javascripts/support/jasmine_runner.rb']
|
||||||
|
end
|
||||||
|
task :server do
|
||||||
|
require 'spec/javascripts/support/jasmine_config'
|
||||||
|
|
||||||
|
puts "your tests are here:"
|
||||||
|
puts " http://localhost:8888/run.html"
|
||||||
|
|
||||||
|
Jasmine::Config.new.start_server
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Run specs via server"
|
||||||
|
task :jasmine => ['jasmine:server']
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
describe('Example', function () {
|
||||||
|
it('should have a passing test', function() {
|
||||||
|
expect(true).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('nested describe', function () {
|
||||||
|
it('should also have a passing test', function () {
|
||||||
|
expect(true).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
//You may load required files here, or create test-runner-wide environment settings.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Return an array of filepaths relative to src_dir to include before jasmine specs.
|
||||||
|
src_files:
|
||||||
|
- javascripts/prototype.js
|
||||||
|
- javascripts/effects.js
|
||||||
|
- javascripts/controls.js
|
||||||
|
- javascripts/dragdrop.js
|
||||||
|
- javascripts/application.js
|
||||||
|
|
||||||
|
# Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
|
||||||
|
stylesheets:
|
||||||
|
- stylesheets/**/*.css
|
||||||
|
# Return an array of filepaths relative to spec_dir to include before jasmine specs.
|
||||||
|
spec_files:
|
||||||
|
- **/*.js
|
||||||
|
|
||||||
|
# Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
|
||||||
|
src_dir: public
|
||||||
|
|
||||||
|
# Spec directory path. Your spec_files must be returned relative to this path.
|
||||||
|
spec_dir: spec/javascripts
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Return an array of filepaths relative to src_dir to include before jasmine specs.
|
||||||
|
#src_files:
|
||||||
|
# - lib/source1.js
|
||||||
|
# - lib/source2.js
|
||||||
|
# - dist/**/*.js
|
||||||
|
|
||||||
|
# Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
|
||||||
|
#stylesheets:
|
||||||
|
# - css/style.css
|
||||||
|
# - stylesheets/*.css
|
||||||
|
|
||||||
|
# Return an array of filepaths relative to spec_dir to include before jasmine specs.
|
||||||
|
#spec_files:
|
||||||
|
# - **/*.js
|
||||||
|
|
||||||
|
# Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
|
||||||
|
#src_dir:
|
||||||
|
|
||||||
|
# Spec directory path. Your spec_files must be returned relative to this path.
|
||||||
|
#spec_dir: spec/javascripts
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
require 'jasmine'
|
||||||
|
|
||||||
|
class Jasmine::Config
|
||||||
|
|
||||||
|
# Override these methods if necessary
|
||||||
|
|
||||||
|
# def project_root
|
||||||
|
# Dir.pwd
|
||||||
|
# end
|
||||||
|
|
||||||
|
# Path to your jasmine.yml
|
||||||
|
# def simple_config_file
|
||||||
|
# File.join(project_root, 'spec/javascripts/support/jasmine.yml')
|
||||||
|
# end
|
||||||
|
|
||||||
|
# Source directory path. Your src_files must be returned relative to this path.
|
||||||
|
# def src_dir
|
||||||
|
# if simple_config['src_dir']
|
||||||
|
# File.join(project_root, simple_config['src_dir'])
|
||||||
|
# else
|
||||||
|
# project_root
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
||||||
|
# Spec directory path. Your spec_files must be returned relative to this path.
|
||||||
|
# def spec_dir
|
||||||
|
# if simple_config['spec_dir']
|
||||||
|
# File.join(project_root, simple_config['spec_dir'])
|
||||||
|
# else
|
||||||
|
# File.join(project_root, 'spec/javascripts')
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
||||||
|
# Return an array of filepaths relative to src_dir to include before jasmine specs.
|
||||||
|
# def src_files
|
||||||
|
# files = []
|
||||||
|
# if simple_config['src_files']
|
||||||
|
# files = simple_config['src_files'].collect {|filepath| Dir.glob(filepath)}
|
||||||
|
# end
|
||||||
|
# files
|
||||||
|
# end
|
||||||
|
|
||||||
|
# Return an array of filepaths relative to spec_dir to include before jasmine specs.
|
||||||
|
# def spec_files
|
||||||
|
# files = match_files(spec_dir, "**/*.js")
|
||||||
|
# if simple_config['spec_files']
|
||||||
|
# files = simple_config['spec_files'].collect {|filepath| Dir.glob(filepath)}
|
||||||
|
# end
|
||||||
|
# files
|
||||||
|
# end
|
||||||
|
|
||||||
|
# Return an array of filepaths relative to src_dir to include before jasmine specs.
|
||||||
|
# def stylesheets
|
||||||
|
# files = []
|
||||||
|
# if simple_config['stylesheets']
|
||||||
|
# files = simple_config['stylesheets'].collect {|filepath| Dir.glob(filepath)}
|
||||||
|
# end
|
||||||
|
# files
|
||||||
|
# end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
require 'rubygems'
|
||||||
|
require File.expand_path(File.join(File.dirname(__FILE__), 'jasmine_config'))
|
||||||
|
|
||||||
|
jasmine_config = Jasmine::Config.new
|
||||||
|
spec_builder = Jasmine::SpecBuilder.new(jasmine_config)
|
||||||
|
|
||||||
|
should_stop = false
|
||||||
|
|
||||||
|
Spec::Runner.configure do |config|
|
||||||
|
config.after(:suite) do
|
||||||
|
spec_builder.stop if should_stop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
spec_builder.start
|
||||||
|
should_stop = true
|
||||||
|
spec_builder.declare_suites
|
||||||
|
Before Width: | Height: | Size: 722 B |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 759 B |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 802 B |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 768 B |
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,2 @@
|
|||||||
|
jasmine_bin = File.expand_path(File.join(File.dirname(__FILE__), 'bin', 'jasmine'))
|
||||||
|
`#{jasmine_bin} init`
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
# Generated by jeweler
|
||||||
|
# DO NOT EDIT THIS FILE DIRECTLY
|
||||||
|
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
Gem::Specification.new do |s|
|
||||||
|
s.name = %q{jasmine}
|
||||||
|
s.version = "0.4.5"
|
||||||
|
|
||||||
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||||
|
s.authors = ["Rajan Agaskar", "Christian Williams"]
|
||||||
|
s.date = %q{2010-02-24}
|
||||||
|
s.default_executable = %q{jasmine}
|
||||||
|
s.description = %q{Javascript BDD test framework}
|
||||||
|
s.email = %q{ragaskar@gmail.com}
|
||||||
|
s.executables = ["jasmine"]
|
||||||
|
s.extra_rdoc_files = [
|
||||||
|
"README.markdown"
|
||||||
|
]
|
||||||
|
s.files = [
|
||||||
|
"generators/jasmine/jasmine_generator.rb",
|
||||||
|
"generators/jasmine/templates/INSTALL",
|
||||||
|
"generators/jasmine/templates/lib/tasks/jasmine.rake",
|
||||||
|
"generators/jasmine/templates/spec/javascripts/ExampleSpec.js",
|
||||||
|
"generators/jasmine/templates/spec/javascripts/SpecHelper.js",
|
||||||
|
"generators/jasmine/templates/spec/javascripts/support/jasmine-rails.yml",
|
||||||
|
"generators/jasmine/templates/spec/javascripts/support/jasmine.yml",
|
||||||
|
"generators/jasmine/templates/spec/javascripts/support/jasmine_config.rb",
|
||||||
|
"generators/jasmine/templates/spec/javascripts/support/jasmine_runner.rb",
|
||||||
|
"jasmine/contrib/ruby/jasmine_runner.rb",
|
||||||
|
"jasmine/contrib/ruby/jasmine_spec_builder.rb",
|
||||||
|
"jasmine/contrib/ruby/run.html",
|
||||||
|
"jasmine/lib/TrivialReporter.js",
|
||||||
|
"jasmine/lib/consolex.js",
|
||||||
|
"jasmine/lib/jasmine-0.10.1.js",
|
||||||
|
"jasmine/lib/jasmine.css",
|
||||||
|
"jasmine/lib/json2.js",
|
||||||
|
"lib/jasmine.rb",
|
||||||
|
"lib/jasmine/base.rb",
|
||||||
|
"lib/jasmine/config.rb",
|
||||||
|
"lib/jasmine/run.html.erb",
|
||||||
|
"lib/jasmine/selenium_driver.rb",
|
||||||
|
"lib/jasmine/server.rb",
|
||||||
|
"lib/jasmine/spec_builder.rb"
|
||||||
|
]
|
||||||
|
s.homepage = %q{http://github.com/pivotal/jasmine-ruby}
|
||||||
|
s.rdoc_options = ["--charset=UTF-8"]
|
||||||
|
s.require_paths = ["lib"]
|
||||||
|
s.rubygems_version = %q{1.3.5}
|
||||||
|
s.summary = %q{Jasmine Ruby Runner}
|
||||||
|
s.test_files = [
|
||||||
|
"spec/config_spec.rb",
|
||||||
|
"spec/jasmine_self_test_config.rb",
|
||||||
|
"spec/jasmine_self_test_spec.rb",
|
||||||
|
"spec/server_spec.rb",
|
||||||
|
"spec/spec_helper.rb"
|
||||||
|
]
|
||||||
|
|
||||||
|
if s.respond_to? :specification_version then
|
||||||
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||||
|
s.specification_version = 3
|
||||||
|
|
||||||
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
||||||
|
s.add_runtime_dependency(%q<rspec>, [">= 1.1.5"])
|
||||||
|
s.add_runtime_dependency(%q<json>, [">= 1.1.9"])
|
||||||
|
s.add_runtime_dependency(%q<rack>, [">= 1.0.0"])
|
||||||
|
s.add_runtime_dependency(%q<thin>, [">= 1.2.4"])
|
||||||
|
s.add_runtime_dependency(%q<selenium-rc>, [">= 2.1.0"])
|
||||||
|
s.add_runtime_dependency(%q<selenium-client>, [">= 1.2.17"])
|
||||||
|
else
|
||||||
|
s.add_dependency(%q<rspec>, [">= 1.1.5"])
|
||||||
|
s.add_dependency(%q<json>, [">= 1.1.9"])
|
||||||
|
s.add_dependency(%q<rack>, [">= 1.0.0"])
|
||||||
|
s.add_dependency(%q<thin>, [">= 1.2.4"])
|
||||||
|
s.add_dependency(%q<selenium-rc>, [">= 2.1.0"])
|
||||||
|
s.add_dependency(%q<selenium-client>, [">= 1.2.17"])
|
||||||
|
end
|
||||||
|
else
|
||||||
|
s.add_dependency(%q<rspec>, [">= 1.1.5"])
|
||||||
|
s.add_dependency(%q<json>, [">= 1.1.9"])
|
||||||
|
s.add_dependency(%q<rack>, [">= 1.0.0"])
|
||||||
|
s.add_dependency(%q<thin>, [">= 1.2.4"])
|
||||||
|
s.add_dependency(%q<selenium-rc>, [">= 2.1.0"])
|
||||||
|
s.add_dependency(%q<selenium-client>, [">= 1.2.17"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/** Console X
|
|
||||||
* http://github.com/deadlyicon/consolex.js
|
|
||||||
*
|
|
||||||
* By Jared Grippe <jared@jaredgrippe.com>
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009 Jared Grippe
|
|
||||||
* Licensed under the MIT license.
|
|
||||||
*
|
|
||||||
* consolex avoids ever having to see javascript bugs in browsers that do not implement the entire
|
|
||||||
* firebug console suit
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
(function(window) {
|
|
||||||
window.console || (window.console = {});
|
|
||||||
|
|
||||||
var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
|
|
||||||
"group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
|
|
||||||
|
|
||||||
function emptyFunction(){}
|
|
||||||
|
|
||||||
for (var i = 0; i < names.length; ++i){
|
|
||||||
window.console[names[i]] || (window.console[names[i]] = emptyFunction);
|
|
||||||
if (typeof window.console[names[i]] !== 'function')
|
|
||||||
window.console[names[i]] = (function(method) {
|
|
||||||
return function(){ return Function.prototype.apply.apply(method, [console,arguments]); };
|
|
||||||
})(window.console[names[i]]);
|
|
||||||
}
|
|
||||||
})(this);
|
|
||||||
@@ -1,182 +0,0 @@
|
|||||||
jasmine.TrivialReporter = function(doc) {
|
|
||||||
this.document = doc || document;
|
|
||||||
this.suiteDivs = {};
|
|
||||||
this.logRunningSpecs = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
|
|
||||||
var el = document.createElement(type);
|
|
||||||
|
|
||||||
for (var i = 2; i < arguments.length; i++) {
|
|
||||||
var child = arguments[i];
|
|
||||||
|
|
||||||
if (typeof child === 'string') {
|
|
||||||
el.appendChild(document.createTextNode(child));
|
|
||||||
} else {
|
|
||||||
if (child) { el.appendChild(child); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var attr in attrs) {
|
|
||||||
if (attr == "className") {
|
|
||||||
el[attr] = attrs[attr];
|
|
||||||
} else {
|
|
||||||
el.setAttribute(attr, attrs[attr]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return el;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
|
||||||
var showPassed, showSkipped;
|
|
||||||
|
|
||||||
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
|
|
||||||
this.createDom('div', { className: 'banner' },
|
|
||||||
this.createDom('div', { className: 'logo' },
|
|
||||||
"Jasmine",
|
|
||||||
this.createDom('span', { className: 'version' }, runner.env.versionString())),
|
|
||||||
this.createDom('div', { className: 'options' },
|
|
||||||
"Show ",
|
|
||||||
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
|
|
||||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
|
|
||||||
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
|
|
||||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
|
|
||||||
)
|
|
||||||
),
|
|
||||||
|
|
||||||
this.runnerDiv = this.createDom('div', { className: 'runner running' },
|
|
||||||
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
|
|
||||||
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
|
|
||||||
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
|
|
||||||
);
|
|
||||||
|
|
||||||
this.document.body.appendChild(this.outerDiv);
|
|
||||||
|
|
||||||
var suites = runner.suites();
|
|
||||||
for (var i = 0; i < suites.length; i++) {
|
|
||||||
var suite = suites[i];
|
|
||||||
var suiteDiv = this.createDom('div', { className: 'suite' },
|
|
||||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
|
|
||||||
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
|
|
||||||
this.suiteDivs[suite.id] = suiteDiv;
|
|
||||||
var parentDiv = this.outerDiv;
|
|
||||||
if (suite.parentSuite) {
|
|
||||||
parentDiv = this.suiteDivs[suite.parentSuite.id];
|
|
||||||
}
|
|
||||||
parentDiv.appendChild(suiteDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.startedAt = new Date();
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
showPassed.onchange = function(evt) {
|
|
||||||
if (evt.target.checked) {
|
|
||||||
self.outerDiv.className += ' show-passed';
|
|
||||||
} else {
|
|
||||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
showSkipped.onchange = function(evt) {
|
|
||||||
if (evt.target.checked) {
|
|
||||||
self.outerDiv.className += ' show-skipped';
|
|
||||||
} else {
|
|
||||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
|
|
||||||
var results = runner.results();
|
|
||||||
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
|
|
||||||
this.runnerDiv.setAttribute("class", className);
|
|
||||||
//do it twice for IE
|
|
||||||
this.runnerDiv.setAttribute("className", className);
|
|
||||||
var specs = runner.specs();
|
|
||||||
var specCount = 0;
|
|
||||||
for (var i = 0; i < specs.length; i++) {
|
|
||||||
if (this.specFilter(specs[i])) {
|
|
||||||
specCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
|
|
||||||
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
|
|
||||||
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
|
|
||||||
|
|
||||||
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
|
|
||||||
var results = suite.results();
|
|
||||||
var status = results.passed() ? 'passed' : 'failed';
|
|
||||||
if (results.totalCount == 0) { // todo: change this to check results.skipped
|
|
||||||
status = 'skipped';
|
|
||||||
}
|
|
||||||
this.suiteDivs[suite.id].className += " " + status;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
|
|
||||||
if (this.logRunningSpecs) {
|
|
||||||
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
|
|
||||||
var results = spec.results();
|
|
||||||
var status = results.passed() ? 'passed' : 'failed';
|
|
||||||
if (results.skipped) {
|
|
||||||
status = 'skipped';
|
|
||||||
}
|
|
||||||
var specDiv = this.createDom('div', { className: 'spec ' + status },
|
|
||||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
|
|
||||||
this.createDom('a', {
|
|
||||||
className: 'description',
|
|
||||||
href: '?spec=' + encodeURIComponent(spec.getFullName()),
|
|
||||||
title: spec.getFullName()
|
|
||||||
}, spec.description));
|
|
||||||
|
|
||||||
|
|
||||||
var resultItems = results.getItems();
|
|
||||||
var messagesDiv = this.createDom('div', { className: 'messages' });
|
|
||||||
for (var i = 0; i < resultItems.length; i++) {
|
|
||||||
var result = resultItems[i];
|
|
||||||
|
|
||||||
if (result.type == 'log') {
|
|
||||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
|
||||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
|
||||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
|
||||||
|
|
||||||
if (result.trace.stack) {
|
|
||||||
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (messagesDiv.childNodes.length > 0) {
|
|
||||||
specDiv.appendChild(messagesDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.suiteDivs[spec.suite.id].appendChild(specDiv);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.log = function() {
|
|
||||||
var console = jasmine.getGlobal().console;
|
|
||||||
if (console && console.log) console.log.apply(console, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.getLocation = function() {
|
|
||||||
return this.document.location;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
|
|
||||||
var paramMap = {};
|
|
||||||
var params = this.getLocation().search.substring(1).split('&');
|
|
||||||
for (var i = 0; i < params.length; i++) {
|
|
||||||
var p = params[i].split('=');
|
|
||||||
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!paramMap["spec"]) return true;
|
|
||||||
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
|
|
||||||
};
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.jasmine_reporter a:visited, .jasmine_reporter a {
|
|
||||||
color: #303;
|
|
||||||
}
|
|
||||||
|
|
||||||
.jasmine_reporter a:hover, .jasmine_reporter a:active {
|
|
||||||
color: blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
.run_spec {
|
|
||||||
float:right;
|
|
||||||
padding-right: 5px;
|
|
||||||
font-size: .8em;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.jasmine_reporter {
|
|
||||||
margin: 0 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner {
|
|
||||||
color: #303;
|
|
||||||
background-color: #fef;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
float: left;
|
|
||||||
font-size: 1.1em;
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo .version {
|
|
||||||
font-size: .6em;
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.runner.running {
|
|
||||||
background-color: yellow;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.options {
|
|
||||||
text-align: right;
|
|
||||||
font-size: .8em;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.suite {
|
|
||||||
border: 1px outset gray;
|
|
||||||
margin: 5px 0;
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.suite .suite {
|
|
||||||
margin: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.suite.passed {
|
|
||||||
background-color: #dfd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.suite.failed {
|
|
||||||
background-color: #fdd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spec {
|
|
||||||
margin: 5px;
|
|
||||||
padding-left: 1em;
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spec.failed, .spec.passed, .spec.skipped {
|
|
||||||
padding-bottom: 5px;
|
|
||||||
border: 1px solid gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spec.failed {
|
|
||||||
background-color: #fbb;
|
|
||||||
border-color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spec.passed {
|
|
||||||
background-color: #bfb;
|
|
||||||
border-color: green;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spec.skipped {
|
|
||||||
background-color: #bbb;
|
|
||||||
}
|
|
||||||
|
|
||||||
.messages {
|
|
||||||
border-left: 1px dashed gray;
|
|
||||||
padding-left: 1em;
|
|
||||||
padding-right: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.passed {
|
|
||||||
background-color: #cfc;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.failed {
|
|
||||||
background-color: #fbb;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skipped {
|
|
||||||
color: #777;
|
|
||||||
background-color: #eee;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*.resultMessage {*/
|
|
||||||
/*white-space: pre;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
.resultMessage span.result {
|
|
||||||
display: block;
|
|
||||||
line-height: 2em;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.resultMessage .mismatch {
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stackTrace {
|
|
||||||
white-space: pre;
|
|
||||||
font-size: .8em;
|
|
||||||
margin-left: 10px;
|
|
||||||
max-height: 5em;
|
|
||||||
overflow: auto;
|
|
||||||
border: 1px inset red;
|
|
||||||
padding: 1em;
|
|
||||||
background: #eef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.finished-at {
|
|
||||||
padding-left: 1em;
|
|
||||||
font-size: .6em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-passed .passed,
|
|
||||||
.show-skipped .skipped {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#jasmine_content {
|
|
||||||
position:fixed;
|
|
||||||
right: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.runner {
|
|
||||||
border: 1px solid gray;
|
|
||||||
display: block;
|
|
||||||
margin: 5px 0;
|
|
||||||
padding: 2px 0 2px 10px;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
require 'jasmine/base'
|
||||||
|
require 'jasmine/config'
|
||||||
|
require 'jasmine/server'
|
||||||
|
require 'jasmine/selenium_driver'
|
||||||
|
|
||||||
|
require 'jasmine/spec_builder'
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
require 'socket'
|
||||||
|
require 'erb'
|
||||||
|
require 'json'
|
||||||
|
|
||||||
|
module Jasmine
|
||||||
|
def self.root
|
||||||
|
File.expand_path(File.join(File.dirname(__FILE__), '../../jasmine'))
|
||||||
|
end
|
||||||
|
|
||||||
|
# this seemingly-over-complex method is necessary to get an open port on at least some of our Macs
|
||||||
|
def self.open_socket_on_unused_port
|
||||||
|
infos = Socket::getaddrinfo("localhost", nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
|
||||||
|
families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten]
|
||||||
|
|
||||||
|
return TCPServer.open('0.0.0.0', 0) if families.has_key?('AF_INET')
|
||||||
|
return TCPServer.open('::', 0) if families.has_key?('AF_INET6')
|
||||||
|
return TCPServer.open(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.find_unused_port
|
||||||
|
socket = open_socket_on_unused_port
|
||||||
|
port = socket.addr[1]
|
||||||
|
socket.close
|
||||||
|
port
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.server_is_listening_on(hostname, port)
|
||||||
|
require 'socket'
|
||||||
|
begin
|
||||||
|
socket = TCPSocket.open(hostname, port)
|
||||||
|
rescue Errno::ECONNREFUSED
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
socket.close
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.wait_for_listener(port, name = "required process", seconds_to_wait = 10)
|
||||||
|
time_out_at = Time.now + seconds_to_wait
|
||||||
|
until server_is_listening_on "localhost", port
|
||||||
|
sleep 0.1
|
||||||
|
puts "Waiting for #{name} on #{port}..."
|
||||||
|
raise "#{name} didn't show up on port #{port} after #{seconds_to_wait} seconds." if Time.now > time_out_at
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.kill_process_group(process_group_id, signal="TERM")
|
||||||
|
Process.kill signal, -process_group_id # negative pid means kill process group. (see man 2 kill)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.cachebust(files, root_dir="", replace=nil, replace_with=nil)
|
||||||
|
require 'digest/md5'
|
||||||
|
files.collect do |file_name|
|
||||||
|
real_file_name = replace && replace_with ? file_name.sub(replace, replace_with) : file_name
|
||||||
|
begin
|
||||||
|
digest = Digest::MD5.hexdigest(File.read("#{root_dir}#{real_file_name}"))
|
||||||
|
rescue
|
||||||
|
digest = "MISSING-FILE"
|
||||||
|
end
|
||||||
|
"#{file_name}?cachebust=#{digest}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
module Jasmine
|
||||||
|
class Config
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
def initialize(options = {})
|
||||||
|
require 'selenium_rc'
|
||||||
|
@selenium_jar_path = SeleniumRC::Server.allocate.jar_path
|
||||||
|
@options = options
|
||||||
|
|
||||||
|
@browser = options[:browser] ? options.delete(:browser) : 'firefox'
|
||||||
|
@selenium_pid = nil
|
||||||
|
@jasmine_server_pid = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_server(port = 8888)
|
||||||
|
Jasmine::Server.new(port, self).start
|
||||||
|
end
|
||||||
|
|
||||||
|
def start
|
||||||
|
start_servers
|
||||||
|
@client = Jasmine::SeleniumDriver.new("localhost", @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/")
|
||||||
|
@client.connect
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
@client.disconnect
|
||||||
|
stop_servers
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_servers
|
||||||
|
@jasmine_server_port = Jasmine::find_unused_port
|
||||||
|
@selenium_server_port = Jasmine::find_unused_port
|
||||||
|
|
||||||
|
server = Jasmine::Server.new(@jasmine_server_port, self)
|
||||||
|
|
||||||
|
@selenium_pid = fork do
|
||||||
|
Process.setpgrp
|
||||||
|
exec "java -jar #{@selenium_jar_path} -port #{@selenium_server_port} > /dev/null 2>&1"
|
||||||
|
end
|
||||||
|
puts "selenium started. pid is #{@selenium_pid}"
|
||||||
|
|
||||||
|
@jasmine_server_pid = fork do
|
||||||
|
Process.setpgrp
|
||||||
|
server.start
|
||||||
|
exit! 0
|
||||||
|
end
|
||||||
|
puts "jasmine server started. pid is #{@jasmine_server_pid}"
|
||||||
|
|
||||||
|
Jasmine::wait_for_listener(@selenium_server_port, "selenium server")
|
||||||
|
Jasmine::wait_for_listener(@jasmine_server_port, "jasmine server")
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop_servers
|
||||||
|
puts "shutting down the servers..."
|
||||||
|
Jasmine::kill_process_group(@selenium_pid) if @selenium_pid
|
||||||
|
Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_pid
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
begin
|
||||||
|
start
|
||||||
|
puts "servers are listening on their ports -- running the test script..."
|
||||||
|
tests_passed = @client.run
|
||||||
|
ensure
|
||||||
|
stop
|
||||||
|
end
|
||||||
|
return tests_passed
|
||||||
|
end
|
||||||
|
|
||||||
|
def eval_js(script)
|
||||||
|
@client.eval_js(script)
|
||||||
|
end
|
||||||
|
|
||||||
|
def match_files(dir, patterns)
|
||||||
|
dir = File.expand_path(dir)
|
||||||
|
patterns.collect do |pattern|
|
||||||
|
Dir.glob(File.join(dir, pattern)).collect {|f| f.sub("#{dir}/", "")}.sort
|
||||||
|
end.flatten
|
||||||
|
end
|
||||||
|
|
||||||
|
def simple_config
|
||||||
|
config = File.exist?(simple_config_file) ? File.open(simple_config_file) { |yf| YAML::load( yf ) } : false
|
||||||
|
config || {}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def spec_path
|
||||||
|
"/__spec__"
|
||||||
|
end
|
||||||
|
|
||||||
|
def root_path
|
||||||
|
"/__root__"
|
||||||
|
end
|
||||||
|
|
||||||
|
def mappings
|
||||||
|
{
|
||||||
|
spec_path => spec_dir,
|
||||||
|
root_path => project_root
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def js_files
|
||||||
|
src_files.collect {|f| "/" + f } + spec_files.collect {|f| File.join(spec_path, f) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def css_files
|
||||||
|
stylesheets.collect {|f| "/" + f }
|
||||||
|
end
|
||||||
|
|
||||||
|
def spec_files_full_paths
|
||||||
|
spec_files.collect {|spec_file| File.join(spec_dir, spec_file) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def project_root
|
||||||
|
Dir.pwd
|
||||||
|
end
|
||||||
|
|
||||||
|
def simple_config_file
|
||||||
|
File.join(project_root, 'spec/javascripts/support/jasmine.yml')
|
||||||
|
end
|
||||||
|
|
||||||
|
def src_dir
|
||||||
|
if simple_config['src_dir']
|
||||||
|
File.join(project_root, simple_config['src_dir'])
|
||||||
|
else
|
||||||
|
project_root
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def spec_dir
|
||||||
|
if simple_config['spec_dir']
|
||||||
|
File.join(project_root, simple_config['spec_dir'])
|
||||||
|
else
|
||||||
|
File.join(project_root, 'spec/javascripts')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def src_files
|
||||||
|
files = []
|
||||||
|
if simple_config['src_files']
|
||||||
|
files = match_files(src_dir, simple_config['src_files'])
|
||||||
|
end
|
||||||
|
files
|
||||||
|
end
|
||||||
|
|
||||||
|
def spec_files
|
||||||
|
files = match_files(spec_dir, "**/*.js")
|
||||||
|
if simple_config['spec_files']
|
||||||
|
files = match_files(spec_dir, simple_config['spec_files'])
|
||||||
|
end
|
||||||
|
files
|
||||||
|
end
|
||||||
|
|
||||||
|
def stylesheets
|
||||||
|
files = []
|
||||||
|
if simple_config['stylesheets']
|
||||||
|
files = match_files(src_dir, simple_config['stylesheets'])
|
||||||
|
end
|
||||||
|
files
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||||
|
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type"/>
|
||||||
|
<title>Jasmine suite</title>
|
||||||
|
<% css_files.each do |css_file| %>
|
||||||
|
<link rel="stylesheet" href="<%= css_file %>" type="text/css" media="screen"/>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% jasmine_files.each do |jasmine_file| %>
|
||||||
|
<script src="<%= jasmine_file %>" type="text/javascript"></script>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var jsApiReporter;
|
||||||
|
(function() {
|
||||||
|
var jasmineEnv = jasmine.getEnv();
|
||||||
|
|
||||||
|
jsApiReporter = new jasmine.JsApiReporter();
|
||||||
|
var trivialReporter = new jasmine.TrivialReporter();
|
||||||
|
|
||||||
|
jasmineEnv.addReporter(jsApiReporter);
|
||||||
|
jasmineEnv.addReporter(trivialReporter);
|
||||||
|
|
||||||
|
jasmineEnv.specFilter = function(spec) {
|
||||||
|
return trivialReporter.specFilter(spec);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
jasmineEnv.execute();
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<% js_files.each do |js_file| %>
|
||||||
|
<script src="<%= js_file %>" type="text/javascript"></script>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="jasmine_content"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
module Jasmine
|
||||||
|
class SeleniumDriver
|
||||||
|
def initialize(selenium_host, selenium_port, selenium_browser_start_command, http_address)
|
||||||
|
require 'selenium/client'
|
||||||
|
@driver = Selenium::Client::Driver.new(
|
||||||
|
selenium_host,
|
||||||
|
selenium_port,
|
||||||
|
selenium_browser_start_command,
|
||||||
|
http_address
|
||||||
|
)
|
||||||
|
@http_address = http_address
|
||||||
|
end
|
||||||
|
|
||||||
|
def tests_have_finished?
|
||||||
|
@driver.get_eval("window.jasmine.getEnv().currentRunner.finished") == "true"
|
||||||
|
end
|
||||||
|
|
||||||
|
def connect
|
||||||
|
@driver.start
|
||||||
|
@driver.open("/")
|
||||||
|
end
|
||||||
|
|
||||||
|
def disconnect
|
||||||
|
@driver.stop
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
until tests_have_finished? do
|
||||||
|
sleep 0.1
|
||||||
|
end
|
||||||
|
|
||||||
|
puts @driver.get_eval("window.results()")
|
||||||
|
failed_count = @driver.get_eval("window.jasmine.getEnv().currentRunner.results().failedCount").to_i
|
||||||
|
failed_count == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def eval_js(script)
|
||||||
|
escaped_script = "'" + script.gsub(/(['\\])/) { '\\' + $1 } + "'"
|
||||||
|
|
||||||
|
result = @driver.get_eval("try { eval(#{escaped_script}, window); } catch(err) { window.eval(#{escaped_script}); }")
|
||||||
|
JSON.parse("{\"result\":#{result}}")["result"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
module Jasmine
|
||||||
|
class RunAdapter
|
||||||
|
def initialize(config)
|
||||||
|
@config = config
|
||||||
|
@jasmine_files = [
|
||||||
|
"/__JASMINE_ROOT__/lib/" + File.basename(Dir.glob("#{Jasmine.root}/lib/jasmine*.js").first),
|
||||||
|
"/__JASMINE_ROOT__/lib/TrivialReporter.js",
|
||||||
|
"/__JASMINE_ROOT__/lib/json2.js",
|
||||||
|
"/__JASMINE_ROOT__/lib/consolex.js",
|
||||||
|
]
|
||||||
|
@jasmine_stylesheets = ["/__JASMINE_ROOT__/lib/jasmine.css"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
return not_found if env["PATH_INFO"] != "/"
|
||||||
|
return [200,{ 'Content-Type' => 'text/html' }, ''] if (env['REQUEST_METHOD'] == 'HEAD')
|
||||||
|
run if env['REQUEST_METHOD'] == 'GET'
|
||||||
|
end
|
||||||
|
|
||||||
|
def not_found
|
||||||
|
body = "File not found: #{@path_info}\n"
|
||||||
|
[404, {"Content-Type" => "text/plain",
|
||||||
|
"Content-Length" => body.size.to_s,
|
||||||
|
"X-Cascade" => "pass"},
|
||||||
|
[body]]
|
||||||
|
end
|
||||||
|
|
||||||
|
#noinspection RubyUnusedLocalVariable
|
||||||
|
def run
|
||||||
|
jasmine_files = @jasmine_files
|
||||||
|
css_files = @jasmine_stylesheets + (@config.css_files || [])
|
||||||
|
js_files = @config.js_files
|
||||||
|
|
||||||
|
body = ERB.new(File.read(File.join(File.dirname(__FILE__), "run.html.erb"))).result(binding)
|
||||||
|
[
|
||||||
|
200,
|
||||||
|
{ 'Content-Type' => 'text/html' },
|
||||||
|
body
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
class Redirect
|
||||||
|
def initialize(url)
|
||||||
|
@url = url
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
[
|
||||||
|
302,
|
||||||
|
{ 'Location' => @url },
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class JsAlert
|
||||||
|
def call(env)
|
||||||
|
[
|
||||||
|
200,
|
||||||
|
{ 'Content-Type' => 'application/javascript' },
|
||||||
|
"document.write('<p>Couldn\\'t load #{env["PATH_INFO"]}!</p>');"
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class FocusedSuite
|
||||||
|
def initialize(config)
|
||||||
|
@config = config
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
spec_files = @config.spec_files_or_proc
|
||||||
|
matching_specs = spec_files.select {|spec_file| spec_file =~ /#{Regexp.escape(env["PATH_INFO"])}/ }.compact
|
||||||
|
if !matching_specs.empty?
|
||||||
|
run_adapter = Jasmine::RunAdapter.new(matching_specs, @options)
|
||||||
|
run_adapter.run
|
||||||
|
else
|
||||||
|
[
|
||||||
|
200,
|
||||||
|
{ 'Content-Type' => 'application/javascript' },
|
||||||
|
"document.write('<p>Couldn\\'t find any specs matching #{env["PATH_INFO"]}!</p>');"
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
class Server
|
||||||
|
attr_reader :thin
|
||||||
|
|
||||||
|
def initialize(port, config)
|
||||||
|
@port = port
|
||||||
|
@config = config
|
||||||
|
|
||||||
|
require 'thin'
|
||||||
|
thin_config = {
|
||||||
|
'/__suite__' => Jasmine::FocusedSuite.new(@config),
|
||||||
|
'/run.html' => Jasmine::Redirect.new('/'),
|
||||||
|
'/' => Jasmine::RunAdapter.new(@config)
|
||||||
|
}
|
||||||
|
|
||||||
|
@config.mappings.each do |from, to|
|
||||||
|
thin_config[from] = Rack::File.new(to)
|
||||||
|
end
|
||||||
|
|
||||||
|
thin_config["/__JASMINE_ROOT__"] = Rack::File.new(Jasmine.root)
|
||||||
|
|
||||||
|
app = Rack::Cascade.new([
|
||||||
|
Rack::URLMap.new({'/' => Rack::File.new(@config.src_dir)}),
|
||||||
|
Rack::URLMap.new(thin_config)
|
||||||
|
# JsAlert.new
|
||||||
|
])
|
||||||
|
# Thin::Logging.trace = true
|
||||||
|
@thin = Thin::Server.new('0.0.0.0', @port, app)
|
||||||
|
end
|
||||||
|
|
||||||
|
def start
|
||||||
|
begin
|
||||||
|
thin.start
|
||||||
|
rescue RuntimeError => e
|
||||||
|
raise e unless e.message == 'no acceptor'
|
||||||
|
raise RuntimeError.new("A server is already running on port #{@port}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
thin.stop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
require 'enumerator'
|
||||||
|
|
||||||
|
module Jasmine
|
||||||
|
class SpecBuilder
|
||||||
|
attr_accessor :suites
|
||||||
|
|
||||||
|
def initialize(config)
|
||||||
|
@config = config
|
||||||
|
@spec_files = config.spec_files
|
||||||
|
@runner = config
|
||||||
|
@spec_ids = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def start
|
||||||
|
guess_example_locations
|
||||||
|
|
||||||
|
@runner.start
|
||||||
|
load_suite_info
|
||||||
|
wait_for_suites_to_finish_running
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
@runner.stop
|
||||||
|
end
|
||||||
|
|
||||||
|
def script_path
|
||||||
|
File.expand_path(__FILE__)
|
||||||
|
end
|
||||||
|
|
||||||
|
def guess_example_locations
|
||||||
|
@example_locations = {}
|
||||||
|
|
||||||
|
example_name_parts = []
|
||||||
|
previous_indent_level = 0
|
||||||
|
@config.spec_files_full_paths.each do |filename|
|
||||||
|
line_number = 1
|
||||||
|
File.open(filename, "r") do |file|
|
||||||
|
file.readlines.each do |line|
|
||||||
|
match = /^(\s*)(describe|it)\s*\(\s*["'](.*)["']\s*,\s*function/.match(line)
|
||||||
|
if (match)
|
||||||
|
indent_level = match[1].length / 2
|
||||||
|
example_name = match[3]
|
||||||
|
example_name_parts[indent_level] = example_name
|
||||||
|
|
||||||
|
full_example_name = example_name_parts.slice(0, indent_level + 1).join(" ")
|
||||||
|
@example_locations[full_example_name] = "#{filename}:#{line_number}: in `it'"
|
||||||
|
end
|
||||||
|
line_number += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_suite_info
|
||||||
|
started = Time.now
|
||||||
|
while !eval_js('jsApiReporter && jsApiReporter.started') do
|
||||||
|
raise "couldn't connect to Jasmine after 60 seconds" if (started + 60 < Time.now)
|
||||||
|
sleep 0.1
|
||||||
|
end
|
||||||
|
|
||||||
|
@suites = eval_js("var result = jsApiReporter.suites(); if (window.Prototype && Object.toJSON) { Object.toJSON(result) } else { JSON.stringify(result) }")
|
||||||
|
end
|
||||||
|
|
||||||
|
def results_for(spec_id)
|
||||||
|
@spec_results ||= load_results
|
||||||
|
@spec_results[spec_id.to_s]
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_results
|
||||||
|
@spec_results = {}
|
||||||
|
@spec_ids.each_slice(50) do |slice|
|
||||||
|
@spec_results.merge!(eval_js("var result = jsApiReporter.resultsForSpecs(#{JSON.generate(slice)}); if (window.Prototype && Object.toJSON) { Object.toJSON(result) } else { JSON.stringify(result) }"))
|
||||||
|
end
|
||||||
|
@spec_results
|
||||||
|
end
|
||||||
|
|
||||||
|
def wait_for_suites_to_finish_running
|
||||||
|
puts "Waiting for suite to finish in browser ..."
|
||||||
|
while !eval_js('jsApiReporter.finished') do
|
||||||
|
sleep 0.1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def declare_suites
|
||||||
|
me = self
|
||||||
|
suites.each do |suite|
|
||||||
|
declare_suite(self, suite)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def declare_suite(parent, suite)
|
||||||
|
me = self
|
||||||
|
parent.describe suite["name"] do
|
||||||
|
suite["children"].each do |suite_or_spec|
|
||||||
|
type = suite_or_spec["type"]
|
||||||
|
if type == "suite"
|
||||||
|
me.declare_suite(self, suite_or_spec)
|
||||||
|
elsif type == "spec"
|
||||||
|
me.declare_spec(self, suite_or_spec)
|
||||||
|
else
|
||||||
|
raise "unknown type #{type} for #{suite_or_spec.inspect}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def declare_spec(parent, spec)
|
||||||
|
me = self
|
||||||
|
example_name = spec["name"]
|
||||||
|
@spec_ids << spec["id"]
|
||||||
|
backtrace = @example_locations[parent.description + " " + example_name]
|
||||||
|
parent.it example_name, {}, backtrace do
|
||||||
|
me.report_spec(spec["id"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def report_spec(spec_id)
|
||||||
|
spec_results = results_for(spec_id)
|
||||||
|
out = ""
|
||||||
|
messages = spec_results['messages'].each do |message|
|
||||||
|
case
|
||||||
|
when message["type"] == "MessageResult"
|
||||||
|
puts message["text"]
|
||||||
|
puts "\n"
|
||||||
|
else
|
||||||
|
unless message["message"] =~ /^Passed.$/
|
||||||
|
STDERR << message["message"]
|
||||||
|
STDERR << "\n"
|
||||||
|
|
||||||
|
out << message["message"]
|
||||||
|
out << "\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
if !message["passed"] && message["trace"]["stack"]
|
||||||
|
stack_trace = message["trace"]["stack"].gsub(/<br \/>/, "\n").gsub(/<\/?b>/, " ")
|
||||||
|
STDERR << stack_trace.gsub(/\(.*\)@http:\/\/localhost:[0-9]+\/specs\//, "/spec/")
|
||||||
|
STDERR << "\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
fail out unless spec_results['result'] == 'passed'
|
||||||
|
puts out unless out.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def eval_js(js)
|
||||||
|
@runner.eval_js(js)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,478 +0,0 @@
|
|||||||
/*
|
|
||||||
http://www.JSON.org/json2.js
|
|
||||||
2009-08-17
|
|
||||||
|
|
||||||
Public Domain.
|
|
||||||
|
|
||||||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
|
||||||
|
|
||||||
See http://www.JSON.org/js.html
|
|
||||||
|
|
||||||
This file creates a global JSON object containing two methods: stringify
|
|
||||||
and parse.
|
|
||||||
|
|
||||||
JSON.stringify(value, replacer, space)
|
|
||||||
value any JavaScript value, usually an object or array.
|
|
||||||
|
|
||||||
replacer an optional parameter that determines how object
|
|
||||||
values are stringified for objects. It can be a
|
|
||||||
function or an array of strings.
|
|
||||||
|
|
||||||
space an optional parameter that specifies the indentation
|
|
||||||
of nested structures. If it is omitted, the text will
|
|
||||||
be packed without extra whitespace. If it is a number,
|
|
||||||
it will specify the number of spaces to indent at each
|
|
||||||
level. If it is a string (such as '\t' or ' '),
|
|
||||||
it contains the characters used to indent at each level.
|
|
||||||
|
|
||||||
This method produces a JSON text from a JavaScript value.
|
|
||||||
|
|
||||||
When an object value is found, if the object contains a toJSON
|
|
||||||
method, its toJSON method will be called and the result will be
|
|
||||||
stringified. A toJSON method does not serialize: it returns the
|
|
||||||
value represented by the name/value pair that should be serialized,
|
|
||||||
or undefined if nothing should be serialized. The toJSON method
|
|
||||||
will be passed the key associated with the value, and this will be
|
|
||||||
bound to the value
|
|
||||||
|
|
||||||
For example, this would serialize Dates as ISO strings.
|
|
||||||
|
|
||||||
Date.prototype.toJSON = function (key) {
|
|
||||||
function f(n) {
|
|
||||||
// Format integers to have at least two digits.
|
|
||||||
return n < 10 ? '0' + n : n;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.getUTCFullYear() + '-' +
|
|
||||||
f(this.getUTCMonth() + 1) + '-' +
|
|
||||||
f(this.getUTCDate()) + 'T' +
|
|
||||||
f(this.getUTCHours()) + ':' +
|
|
||||||
f(this.getUTCMinutes()) + ':' +
|
|
||||||
f(this.getUTCSeconds()) + 'Z';
|
|
||||||
};
|
|
||||||
|
|
||||||
You can provide an optional replacer method. It will be passed the
|
|
||||||
key and value of each member, with this bound to the containing
|
|
||||||
object. The value that is returned from your method will be
|
|
||||||
serialized. If your method returns undefined, then the member will
|
|
||||||
be excluded from the serialization.
|
|
||||||
|
|
||||||
If the replacer parameter is an array of strings, then it will be
|
|
||||||
used to select the members to be serialized. It filters the results
|
|
||||||
such that only members with keys listed in the replacer array are
|
|
||||||
stringified.
|
|
||||||
|
|
||||||
Values that do not have JSON representations, such as undefined or
|
|
||||||
functions, will not be serialized. Such values in objects will be
|
|
||||||
dropped; in arrays they will be replaced with null. You can use
|
|
||||||
a replacer function to replace those with JSON values.
|
|
||||||
JSON.stringify(undefined) returns undefined.
|
|
||||||
|
|
||||||
The optional space parameter produces a stringification of the
|
|
||||||
value that is filled with line breaks and indentation to make it
|
|
||||||
easier to read.
|
|
||||||
|
|
||||||
If the space parameter is a non-empty string, then that string will
|
|
||||||
be used for indentation. If the space parameter is a number, then
|
|
||||||
the indentation will be that many spaces.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
|
||||||
// text is '["e",{"pluribus":"unum"}]'
|
|
||||||
|
|
||||||
|
|
||||||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
|
||||||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
|
||||||
|
|
||||||
text = JSON.stringify([new Date()], function (key, value) {
|
|
||||||
return this[key] instanceof Date ?
|
|
||||||
'Date(' + this[key] + ')' : value;
|
|
||||||
});
|
|
||||||
// text is '["Date(---current time---)"]'
|
|
||||||
|
|
||||||
|
|
||||||
JSON.parse(text, reviver)
|
|
||||||
This method parses a JSON text to produce an object or array.
|
|
||||||
It can throw a SyntaxError exception.
|
|
||||||
|
|
||||||
The optional reviver parameter is a function that can filter and
|
|
||||||
transform the results. It receives each of the keys and values,
|
|
||||||
and its return value is used instead of the original value.
|
|
||||||
If it returns what it received, then the structure is not modified.
|
|
||||||
If it returns undefined then the member is deleted.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
// Parse the text. Values that look like ISO date strings will
|
|
||||||
// be converted to Date objects.
|
|
||||||
|
|
||||||
myData = JSON.parse(text, function (key, value) {
|
|
||||||
var a;
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
a =
|
|
||||||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
|
||||||
if (a) {
|
|
||||||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
|
||||||
+a[5], +a[6]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
|
|
||||||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
|
||||||
var d;
|
|
||||||
if (typeof value === 'string' &&
|
|
||||||
value.slice(0, 5) === 'Date(' &&
|
|
||||||
value.slice(-1) === ')') {
|
|
||||||
d = new Date(value.slice(5, -1));
|
|
||||||
if (d) {
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
This is a reference implementation. You are free to copy, modify, or
|
|
||||||
redistribute.
|
|
||||||
|
|
||||||
This code should be minified before deployment.
|
|
||||||
See http://javascript.crockford.com/jsmin.html
|
|
||||||
|
|
||||||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
|
||||||
NOT CONTROL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*jslint evil: true */
|
|
||||||
|
|
||||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
|
||||||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
|
||||||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
|
||||||
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
|
||||||
test, toJSON, toString, valueOf
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// Create a JSON object only if one does not already exist. We create the
|
|
||||||
// methods in a closure to avoid creating global variables.
|
|
||||||
|
|
||||||
if (!this.JSON) {
|
|
||||||
this.JSON = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
|
|
||||||
function f(n) {
|
|
||||||
// Format integers to have at least two digits.
|
|
||||||
return n < 10 ? '0' + n : n;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof Date.prototype.toJSON !== 'function') {
|
|
||||||
|
|
||||||
Date.prototype.toJSON = function (key) {
|
|
||||||
|
|
||||||
return isFinite(this.valueOf()) ?
|
|
||||||
this.getUTCFullYear() + '-' +
|
|
||||||
f(this.getUTCMonth() + 1) + '-' +
|
|
||||||
f(this.getUTCDate()) + 'T' +
|
|
||||||
f(this.getUTCHours()) + ':' +
|
|
||||||
f(this.getUTCMinutes()) + ':' +
|
|
||||||
f(this.getUTCSeconds()) + 'Z' : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
String.prototype.toJSON =
|
|
||||||
Number.prototype.toJSON =
|
|
||||||
Boolean.prototype.toJSON = function (key) {
|
|
||||||
return this.valueOf();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
||||||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
||||||
gap,
|
|
||||||
indent,
|
|
||||||
meta = { // table of character substitutions
|
|
||||||
'\b': '\\b',
|
|
||||||
'\t': '\\t',
|
|
||||||
'\n': '\\n',
|
|
||||||
'\f': '\\f',
|
|
||||||
'\r': '\\r',
|
|
||||||
'"' : '\\"',
|
|
||||||
'\\': '\\\\'
|
|
||||||
},
|
|
||||||
rep;
|
|
||||||
|
|
||||||
|
|
||||||
function quote(string) {
|
|
||||||
|
|
||||||
// If the string contains no control characters, no quote characters, and no
|
|
||||||
// backslash characters, then we can safely slap some quotes around it.
|
|
||||||
// Otherwise we must also replace the offending characters with safe escape
|
|
||||||
// sequences.
|
|
||||||
|
|
||||||
escapable.lastIndex = 0;
|
|
||||||
return escapable.test(string) ?
|
|
||||||
'"' + string.replace(escapable, function (a) {
|
|
||||||
var c = meta[a];
|
|
||||||
return typeof c === 'string' ? c :
|
|
||||||
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
||||||
}) + '"' :
|
|
||||||
'"' + string + '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function str(key, holder) {
|
|
||||||
// Produce a string from holder[key].
|
|
||||||
|
|
||||||
var i, // The loop counter.
|
|
||||||
k, // The member key.
|
|
||||||
v, // The member value.
|
|
||||||
length,
|
|
||||||
mind = gap,
|
|
||||||
partial,
|
|
||||||
value = holder[key];
|
|
||||||
|
|
||||||
// If the value has a toJSON method, call it to obtain a replacement value.
|
|
||||||
|
|
||||||
if (value && typeof value === 'object' &&
|
|
||||||
typeof value.toJSON === 'function') {
|
|
||||||
value = value.toJSON(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we were called with a replacer function, then call the replacer to
|
|
||||||
// obtain a replacement value.
|
|
||||||
|
|
||||||
if (typeof rep === 'function') {
|
|
||||||
value = rep.call(holder, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// What happens next depends on the value's type.
|
|
||||||
|
|
||||||
switch (typeof value) {
|
|
||||||
case 'string':
|
|
||||||
return quote(value);
|
|
||||||
|
|
||||||
case 'number':
|
|
||||||
|
|
||||||
// JSON numbers must be finite. Encode non-finite numbers as null.
|
|
||||||
|
|
||||||
return isFinite(value) ? String(value) : 'null';
|
|
||||||
|
|
||||||
case 'boolean':
|
|
||||||
case 'null':
|
|
||||||
|
|
||||||
// If the value is a boolean or null, convert it to a string. Note:
|
|
||||||
// typeof null does not produce 'null'. The case is included here in
|
|
||||||
// the remote chance that this gets fixed someday.
|
|
||||||
|
|
||||||
return String(value);
|
|
||||||
|
|
||||||
// If the type is 'object', we might be dealing with an object or an array or
|
|
||||||
// null.
|
|
||||||
|
|
||||||
case 'object':
|
|
||||||
|
|
||||||
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
|
||||||
// so watch out for that case.
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
return 'null';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make an array to hold the partial results of stringifying this object value.
|
|
||||||
|
|
||||||
gap += indent;
|
|
||||||
partial = [];
|
|
||||||
|
|
||||||
// Is the value an array?
|
|
||||||
|
|
||||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
|
||||||
|
|
||||||
// The value is an array. Stringify every element. Use null as a placeholder
|
|
||||||
// for non-JSON values.
|
|
||||||
|
|
||||||
length = value.length;
|
|
||||||
for (i = 0; i < length; i += 1) {
|
|
||||||
partial[i] = str(i, value) || 'null';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join all of the elements together, separated with commas, and wrap them in
|
|
||||||
// brackets.
|
|
||||||
|
|
||||||
v = partial.length === 0 ? '[]' :
|
|
||||||
gap ? '[\n' + gap +
|
|
||||||
partial.join(',\n' + gap) + '\n' +
|
|
||||||
mind + ']' :
|
|
||||||
'[' + partial.join(',') + ']';
|
|
||||||
gap = mind;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the replacer is an array, use it to select the members to be stringified.
|
|
||||||
|
|
||||||
if (rep && typeof rep === 'object') {
|
|
||||||
length = rep.length;
|
|
||||||
for (i = 0; i < length; i += 1) {
|
|
||||||
k = rep[i];
|
|
||||||
if (typeof k === 'string') {
|
|
||||||
v = str(k, value);
|
|
||||||
if (v) {
|
|
||||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Otherwise, iterate through all of the keys in the object.
|
|
||||||
|
|
||||||
for (k in value) {
|
|
||||||
if (Object.hasOwnProperty.call(value, k)) {
|
|
||||||
v = str(k, value);
|
|
||||||
if (v) {
|
|
||||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join all of the member texts together, separated with commas,
|
|
||||||
// and wrap them in braces.
|
|
||||||
|
|
||||||
v = partial.length === 0 ? '{}' :
|
|
||||||
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
|
||||||
mind + '}' : '{' + partial.join(',') + '}';
|
|
||||||
gap = mind;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the JSON object does not yet have a stringify method, give it one.
|
|
||||||
|
|
||||||
if (typeof JSON.stringify !== 'function') {
|
|
||||||
JSON.stringify = function (value, replacer, space) {
|
|
||||||
// The stringify method takes a value and an optional replacer, and an optional
|
|
||||||
// space parameter, and returns a JSON text. The replacer can be a function
|
|
||||||
// that can replace values, or an array of strings that will select the keys.
|
|
||||||
// A default replacer method can be provided. Use of the space parameter can
|
|
||||||
// produce text that is more easily readable.
|
|
||||||
|
|
||||||
var i;
|
|
||||||
gap = '';
|
|
||||||
indent = '';
|
|
||||||
|
|
||||||
// If the space parameter is a number, make an indent string containing that
|
|
||||||
// many spaces.
|
|
||||||
|
|
||||||
if (typeof space === 'number') {
|
|
||||||
for (i = 0; i < space; i += 1) {
|
|
||||||
indent += ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the space parameter is a string, it will be used as the indent string.
|
|
||||||
|
|
||||||
} else if (typeof space === 'string') {
|
|
||||||
indent = space;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is a replacer, it must be a function or an array.
|
|
||||||
// Otherwise, throw an error.
|
|
||||||
|
|
||||||
rep = replacer;
|
|
||||||
if (replacer && typeof replacer !== 'function' &&
|
|
||||||
(typeof replacer !== 'object' ||
|
|
||||||
typeof replacer.length !== 'number')) {
|
|
||||||
throw new Error('JSON.stringify');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a fake root object containing our value under the key of ''.
|
|
||||||
// Return the result of stringifying the value.
|
|
||||||
|
|
||||||
return str('', {'': value});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// If the JSON object does not yet have a parse method, give it one.
|
|
||||||
|
|
||||||
if (typeof JSON.parse !== 'function') {
|
|
||||||
JSON.parse = function (text, reviver) {
|
|
||||||
|
|
||||||
// The parse method takes a text and an optional reviver function, and returns
|
|
||||||
// a JavaScript value if the text is a valid JSON text.
|
|
||||||
|
|
||||||
var j;
|
|
||||||
|
|
||||||
function walk(holder, key) {
|
|
||||||
|
|
||||||
// The walk method is used to recursively walk the resulting structure so
|
|
||||||
// that modifications can be made.
|
|
||||||
|
|
||||||
var k, v, value = holder[key];
|
|
||||||
if (value && typeof value === 'object') {
|
|
||||||
for (k in value) {
|
|
||||||
if (Object.hasOwnProperty.call(value, k)) {
|
|
||||||
v = walk(value, k);
|
|
||||||
if (v !== undefined) {
|
|
||||||
value[k] = v;
|
|
||||||
} else {
|
|
||||||
delete value[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return reviver.call(holder, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Parsing happens in four stages. In the first stage, we replace certain
|
|
||||||
// Unicode characters with escape sequences. JavaScript handles many characters
|
|
||||||
// incorrectly, either silently deleting them, or treating them as line endings.
|
|
||||||
|
|
||||||
cx.lastIndex = 0;
|
|
||||||
if (cx.test(text)) {
|
|
||||||
text = text.replace(cx, function (a) {
|
|
||||||
return '\\u' +
|
|
||||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// In the second stage, we run the text against regular expressions that look
|
|
||||||
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
|
||||||
// because they can cause invocation, and '=' because it can cause mutation.
|
|
||||||
// But just to be safe, we want to reject all unexpected forms.
|
|
||||||
|
|
||||||
// We split the second stage into 4 regexp operations in order to work around
|
|
||||||
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
|
||||||
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
|
||||||
// replace all simple value tokens with ']' characters. Third, we delete all
|
|
||||||
// open brackets that follow a colon or comma or that begin the text. Finally,
|
|
||||||
// we look to see that the remaining characters are only whitespace or ']' or
|
|
||||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
|
||||||
|
|
||||||
if (/^[\],:{}\s]*$/.
|
|
||||||
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
|
|
||||||
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
|
||||||
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
|
||||||
|
|
||||||
// In the third stage we use the eval function to compile the text into a
|
|
||||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
|
||||||
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
|
||||||
// in parens to eliminate the ambiguity.
|
|
||||||
|
|
||||||
j = eval('(' + text + ')');
|
|
||||||
|
|
||||||
// In the optional fourth stage, we recursively walk the new structure, passing
|
|
||||||
// each name/value pair to a reviver function for possible transformation.
|
|
||||||
|
|
||||||
return typeof reviver === 'function' ?
|
|
||||||
walk({'': j}, '') : j;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
|
||||||
|
|
||||||
throw new SyntaxError('JSON.parse');
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
||||||
|
|
||||||
|
describe Jasmine::Config do
|
||||||
|
before(:each) do
|
||||||
|
@template_dir = File.expand_path(File.join(File.dirname(__FILE__), "../generators/jasmine/templates"))
|
||||||
|
@config = Jasmine::Config.new
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "configuration" do
|
||||||
|
before(:each) do
|
||||||
|
@config.stub!(:src_dir).and_return(File.join(@template_dir, "public"))
|
||||||
|
@config.stub!(:spec_dir).and_return(File.join(@template_dir, "spec"))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "if sources.yaml not found" do
|
||||||
|
File.stub!(:exist?).and_return(false)
|
||||||
|
@config.src_files.should == []
|
||||||
|
@config.stylesheets.should == []
|
||||||
|
@config.spec_files.should == ['javascripts/ExampleSpec.js', 'javascripts/SpecHelper.js']
|
||||||
|
@config.mappings.should == {
|
||||||
|
'/__root__' => @config.project_root,
|
||||||
|
'/__spec__' => @config.spec_dir
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it "if jasmine.yml is empty" do
|
||||||
|
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine.yml'))
|
||||||
|
YAML.stub!(:load).and_return(false)
|
||||||
|
@config.src_files.should == []
|
||||||
|
@config.stylesheets.should == []
|
||||||
|
@config.spec_files.should == ['javascripts/ExampleSpec.js', 'javascripts/SpecHelper.js']
|
||||||
|
@config.mappings.should == {
|
||||||
|
'/__root__' => @config.project_root,
|
||||||
|
'/__spec__' => @config.spec_dir
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it "using default jasmine.yml" do
|
||||||
|
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine.yml'))
|
||||||
|
@config.src_files.should == []
|
||||||
|
@config.spec_files.should == ['javascripts/ExampleSpec.js', 'javascripts/SpecHelper.js']
|
||||||
|
@config.mappings.should == {
|
||||||
|
'/__root__' => @config.project_root,
|
||||||
|
'/__spec__' => @config.spec_dir
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it "simple_config stylesheets" do
|
||||||
|
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine.yml'))
|
||||||
|
YAML.stub!(:load).and_return({'stylesheets' => ['foo.css', 'bar.css']})
|
||||||
|
Dir.stub!(:glob).and_return do |glob_string|
|
||||||
|
glob_string
|
||||||
|
end
|
||||||
|
@config.stylesheets.should == ['foo.css', 'bar.css']
|
||||||
|
end
|
||||||
|
|
||||||
|
it "using rails jasmine.yml" do
|
||||||
|
original_glob = Dir.method(:glob)
|
||||||
|
Dir.stub!(:glob).and_return do |glob_string|
|
||||||
|
if glob_string =~ /public/
|
||||||
|
glob_string
|
||||||
|
else
|
||||||
|
original_glob.call(glob_string)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine-rails.yml'))
|
||||||
|
@config.spec_files.should == ['javascripts/ExampleSpec.js', 'javascripts/SpecHelper.js']
|
||||||
|
@config.src_files.should == ['javascripts/prototype.js',
|
||||||
|
'javascripts/effects.js',
|
||||||
|
'javascripts/controls.js',
|
||||||
|
'javascripts/dragdrop.js',
|
||||||
|
'javascripts/application.js']
|
||||||
|
@config.js_files.should == [
|
||||||
|
'/javascripts/prototype.js',
|
||||||
|
'/javascripts/effects.js',
|
||||||
|
'/javascripts/controls.js',
|
||||||
|
'/javascripts/dragdrop.js',
|
||||||
|
'/javascripts/application.js',
|
||||||
|
'/__spec__/javascripts/ExampleSpec.js',
|
||||||
|
'/__spec__/javascripts/SpecHelper.js',
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should provide a list of all spec files with full paths" do
|
||||||
|
@config.spec_files_full_paths.should == [
|
||||||
|
File.join(@template_dir, 'spec/javascripts/ExampleSpec.js'),
|
||||||
|
File.join(@template_dir, 'spec/javascripts/SpecHelper.js')
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
it "src_dir uses root when src dir is blank" do
|
||||||
|
@config.stub!(:project_root).and_return('some_project_root')
|
||||||
|
@config.stub!(:simple_config_file).and_return(File.join(@template_dir, 'spec/javascripts/support/jasmine.yml'))
|
||||||
|
YAML.stub!(:load).and_return({'src_dir' => nil})
|
||||||
|
@config.src_dir.should == 'some_project_root'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should use correct default yaml config" do
|
||||||
|
@config.stub!(:project_root).and_return('some_project_root')
|
||||||
|
@config.simple_config_file.should == (File.join('some_project_root', 'spec/javascripts/support/jasmine.yml'))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
it "should provide dir mappings" do
|
||||||
|
@config.mappings.should == {
|
||||||
|
'/__root__' => @config.project_root,
|
||||||
|
'/__spec__' => @config.spec_dir
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
require 'jasmine'
|
||||||
|
|
||||||
|
class JasmineSelfTestConfig < Jasmine::Config
|
||||||
|
def project_root
|
||||||
|
File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
||||||
|
end
|
||||||
|
|
||||||
|
def src_dir
|
||||||
|
File.join(project_root, 'src')
|
||||||
|
end
|
||||||
|
|
||||||
|
def spec_dir
|
||||||
|
File.join(project_root, 'jasmine/spec')
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
||||||
|
|
||||||
|
require 'jasmine_self_test_config'
|
||||||
|
|
||||||
|
jasmine_config = JasmineSelfTestConfig.new
|
||||||
|
spec_builder = Jasmine::SpecBuilder.new(jasmine_config)
|
||||||
|
|
||||||
|
should_stop = false
|
||||||
|
|
||||||
|
Spec::Runner.configure do |config|
|
||||||
|
config.after(:suite) do
|
||||||
|
spec_builder.stop if should_stop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
spec_builder.start
|
||||||
|
should_stop = true
|
||||||
|
spec_builder.declare_suites
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/html4/loose.dtd">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Jasmine Test Runner</title>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
// yes, really keep this here to keep us honest, but only for jasmine's own runner! [xw]
|
|
||||||
undefined = "diz be undefined yo";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="../src/base.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/util.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/Env.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/Reporter.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/Block.js"></script>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="../src/JsApiReporter.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/Matchers.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/mock-timeout.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/MultiReporter.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/NestedResults.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/PrettyPrinter.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/Queue.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/Runner.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/Spec.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/Suite.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/WaitsBlock.js"></script>
|
|
||||||
<script type="text/javascript" src="../src/WaitsForBlock.js"></script>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="../src/html/TrivialReporter.js"></script>
|
|
||||||
<script type="text/javascript" src="../lib/consolex.js"></script>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript" src="suites/BaseSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/CustomMatchersSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/EnvSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/ExceptionsSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/JsApiReporterSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/MatchersSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/MockClockSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/MultiReporterSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/NestedResultsSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/PrettyPrintSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/ReporterSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/RunnerSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/QueueSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/SpecSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/SpecRunningSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/SpySpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/SuiteSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/TrivialReporterSpec.js"></script>
|
|
||||||
<script type="text/javascript" src="suites/WaitsForBlockSpec.js"></script>
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
(function() {
|
|
||||||
var jasmineEnv = jasmine.getEnv();
|
|
||||||
jasmineEnv.updateInterval = 1000;
|
|
||||||
|
|
||||||
var trivialReporter = new jasmine.TrivialReporter();
|
|
||||||
|
|
||||||
jasmineEnv.addReporter(trivialReporter);
|
|
||||||
|
|
||||||
jasmineEnv.specFilter = function(spec) {
|
|
||||||
return trivialReporter.specFilter(spec);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.onload = function() {
|
|
||||||
jasmineEnv.execute();
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<link href="../src/html/jasmine.css" rel="stylesheet"/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
||||||
|
|
||||||
|
def read(body)
|
||||||
|
return body if body.is_a?(String)
|
||||||
|
out = ""
|
||||||
|
body.each {|data| out += data }
|
||||||
|
out
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Jasmine::Server do
|
||||||
|
before(:each) do
|
||||||
|
config = Jasmine::Config.new
|
||||||
|
config.stub!(:mappings).and_return({
|
||||||
|
"/src" => File.join(Jasmine.root, "src"),
|
||||||
|
"/spec" => File.join(Jasmine.root, "spec")
|
||||||
|
})
|
||||||
|
|
||||||
|
config.stub!(:js_files).and_return(["/src/file1.js", "/spec/file2.js"])
|
||||||
|
|
||||||
|
@server = Jasmine::Server.new(0, config)
|
||||||
|
@thin_app = @server.thin.app
|
||||||
|
end
|
||||||
|
|
||||||
|
after(:each) do
|
||||||
|
@server.thin.stop if @server && @server.thin.running?
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should serve static files" do
|
||||||
|
code, headers, body = @thin_app.call("PATH_INFO" => "/spec/suites/EnvSpec.js", "SCRIPT_NAME" => "xxx")
|
||||||
|
code.should == 200
|
||||||
|
headers["Content-Type"].should == "application/javascript"
|
||||||
|
read(body).should == File.read(File.join(Jasmine.root, "spec/suites/EnvSpec.js"))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should serve Jasmine static files under /__JASMINE_ROOT__/" do
|
||||||
|
code, headers, body = @thin_app.call("PATH_INFO" => "/__JASMINE_ROOT__/lib/jasmine.css", "SCRIPT_NAME" => "xxx")
|
||||||
|
code.should == 200
|
||||||
|
headers["Content-Type"].should == "text/css"
|
||||||
|
read(body).should == File.read(File.join(Jasmine.root, "lib/jasmine.css"))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should redirect /run.html to /" do
|
||||||
|
code, headers, body = @thin_app.call("PATH_INFO" => "/run.html", "SCRIPT_NAME" => "xxx")
|
||||||
|
code.should == 302
|
||||||
|
headers["Location"].should == "/"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should 404 non-existent files" do
|
||||||
|
code, headers, body = @thin_app.call("PATH_INFO" => "/some-non-existent-file", "SCRIPT_NAME" => "xxx")
|
||||||
|
code.should == 404
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "/ page" do
|
||||||
|
it "should load each js file in order" do
|
||||||
|
code, headers, body = @thin_app.call("PATH_INFO" => "/", "SCRIPT_NAME" => "xxx", "REQUEST_METHOD" => 'GET')
|
||||||
|
code.should == 200
|
||||||
|
body = read(body)
|
||||||
|
body.should include("\"/src/file1.js")
|
||||||
|
body.should include("\"/spec/file2.js")
|
||||||
|
body.should satisfy {|s| s.index("/src/file1.js") < s.index("/spec/file2.js") }
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return an empty 200 for HEAD requests to /" do
|
||||||
|
code, headers, body = @thin_app.call("PATH_INFO" => "/", "SCRIPT_NAME" => "xxx", "REQUEST_METHOD" => 'HEAD')
|
||||||
|
code.should == 200
|
||||||
|
headers.should == { 'Content-Type' => 'text/html' }
|
||||||
|
body.should == ''
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
require 'spec'
|
||||||
|
|
||||||
|
require File.expand_path(File.join(File.dirname(__FILE__), "../lib/jasmine"))
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
describe("base.js", function() {
|
|
||||||
describe("jasmine.MessageResult", function() {
|
|
||||||
it("#toString should pretty-print and concatenate each part of the message", function() {
|
|
||||||
var values = ["log", "message", 123, {key: "value"}, "FTW!"];
|
|
||||||
var messageResult = new jasmine.MessageResult(values);
|
|
||||||
expect(messageResult.toString()).toEqual("log message 123 { key : 'value' } FTW!");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("jasmine.log", function() {
|
|
||||||
it("should accept n arguments", function() {
|
|
||||||
spyOn(jasmine.getEnv().currentSpec, 'log');
|
|
||||||
jasmine.log(1, 2, 3);
|
|
||||||
expect(jasmine.getEnv().currentSpec.log).toHaveBeenCalledWith(1, 2, 3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("jasmine.getGlobal", function() {
|
|
||||||
it("should return the global object", function() {
|
|
||||||
var globalObject = (function() {
|
|
||||||
return this;
|
|
||||||
})();
|
|
||||||
|
|
||||||
expect(jasmine.getGlobal()).toBe(globalObject);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
describe("Custom Matchers", function() {
|
|
||||||
var env;
|
|
||||||
var fakeTimer;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
env = new jasmine.Env();
|
|
||||||
env.updateInterval = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should be easy to add more matchers local to a spec, suite, etc.", function() {
|
|
||||||
var spec1, spec2, spec1Matcher, spec2Matcher;
|
|
||||||
var suite = env.describe('some suite', function() {
|
|
||||||
env.beforeEach(function() {
|
|
||||||
this.addMatchers({ matcherForSuite: function(expected) {
|
|
||||||
return "matcherForSuite: actual: " + this.actual + "; expected: " + expected;
|
|
||||||
} });
|
|
||||||
});
|
|
||||||
|
|
||||||
spec1 = env.it('spec with an expectation').runs(function () {
|
|
||||||
this.addMatchers({ matcherForSpec: function(expected) {
|
|
||||||
return "matcherForSpec: actual: " + this.actual + "; expected: " + expected;
|
|
||||||
} });
|
|
||||||
spec1Matcher = this.expect("xxx");
|
|
||||||
});
|
|
||||||
|
|
||||||
spec2 = env.it('spec with failing expectation').runs(function () {
|
|
||||||
spec2Matcher = this.expect("yyy");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.execute();
|
|
||||||
|
|
||||||
expect(spec1Matcher.matcherForSuite("expected")).toEqual("matcherForSuite: actual: xxx; expected: expected");
|
|
||||||
expect(spec1Matcher.matcherForSpec("expected")).toEqual("matcherForSpec: actual: xxx; expected: expected");
|
|
||||||
|
|
||||||
expect(spec2Matcher.matcherForSuite("expected")).toEqual("matcherForSuite: actual: yyy; expected: expected");
|
|
||||||
expect(spec2Matcher.matcherForSpec).toBe(jasmine.undefined);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should generate messages with the same rules as for regular matchers when this.report() is not called", function() {
|
|
||||||
var spec;
|
|
||||||
var suite = env.describe('some suite', function() {
|
|
||||||
spec = env.it('spec with an expectation').runs(function () {
|
|
||||||
this.addMatchers({
|
|
||||||
toBeTrue: function() {
|
|
||||||
return this.actual === true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.expect(true).toBeTrue();
|
|
||||||
this.expect(false).toBeTrue();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.execute();
|
|
||||||
var passResult = new jasmine.ExpectationResult({passed: true, matcherName: 'toBeTrue',
|
|
||||||
actual: true, expected: jasmine.undefined, message: "Passed." });
|
|
||||||
var failResult = new jasmine.ExpectationResult({passed: false, matcherName: 'toBeTrue',
|
|
||||||
actual: false, expected: jasmine.undefined, message: "Expected false to be true." });
|
|
||||||
failResult.trace = jasmine.any(Object);
|
|
||||||
expect(spec.results().getItems()).toEqual([passResult, failResult]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should pass args", function() {
|
|
||||||
var matcherCallArgs = [];
|
|
||||||
var spec;
|
|
||||||
var suite = env.describe('some suite', function() {
|
|
||||||
spec = env.it('spec with an expectation').runs(function () {
|
|
||||||
this.addMatchers({
|
|
||||||
toBeTrue: function() {
|
|
||||||
matcherCallArgs.push(jasmine.util.argsToArray(arguments));
|
|
||||||
return this.actual === true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.expect(true).toBeTrue();
|
|
||||||
this.expect(false).toBeTrue('arg');
|
|
||||||
this.expect(true).toBeTrue('arg1', 'arg2');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite.execute();
|
|
||||||
var results = spec.results().getItems();
|
|
||||||
expect(results[0].expected).toEqual(jasmine.undefined);
|
|
||||||
expect(results[1].expected).toEqual('arg');
|
|
||||||
expect(results[2].expected).toEqual(['arg1', 'arg2']);
|
|
||||||
|
|
||||||
expect(matcherCallArgs).toEqual([[], ['arg'], ['arg1', 'arg2']]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
describe("jasmine.Env", function() {
|
|
||||||
var env;
|
|
||||||
beforeEach(function() {
|
|
||||||
env = new jasmine.Env();
|
|
||||||
env.updateInterval = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('ids', function () {
|
|
||||||
it('nextSpecId should return consecutive integers, starting at 0', function () {
|
|
||||||
expect(env.nextSpecId()).toEqual(0);
|
|
||||||
expect(env.nextSpecId()).toEqual(1);
|
|
||||||
expect(env.nextSpecId()).toEqual(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("reporting", function() {
|
|
||||||
var fakeReporter;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
fakeReporter = jasmine.createSpyObj("fakeReporter", ["log"]);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('version', function () {
|
|
||||||
var oldVersion;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
oldVersion = jasmine.version_;
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(function () {
|
|
||||||
jasmine.version_ = oldVersion;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should raise an error if version is not set', function () {
|
|
||||||
jasmine.version_ = null;
|
|
||||||
var exception;
|
|
||||||
try {
|
|
||||||
env.version();
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
exception = e;
|
|
||||||
}
|
|
||||||
expect(exception.message).toEqual('Version not set');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("version should return the current version as an int", function() {
|
|
||||||
jasmine.version_ = {
|
|
||||||
"major": 1,
|
|
||||||
"minor": 9,
|
|
||||||
"build": 7,
|
|
||||||
"revision": 8
|
|
||||||
};
|
|
||||||
expect(env.version()).toEqual({
|
|
||||||
"major": 1,
|
|
||||||
"minor": 9,
|
|
||||||
"build": 7,
|
|
||||||
"revision": 8
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("versionString", function() {
|
|
||||||
it("should return a stringified version number", function() {
|
|
||||||
jasmine.version_ = {
|
|
||||||
"major": 1,
|
|
||||||
"minor": 9,
|
|
||||||
"build": 7,
|
|
||||||
"revision": 8
|
|
||||||
};
|
|
||||||
expect(env.versionString()).toEqual("1.9.7 revision 8");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return a nice string when version is unknown", function() {
|
|
||||||
jasmine.version_ = null;
|
|
||||||
expect(env.versionString()).toEqual("version unknown");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should allow reporters to be registered", function() {
|
|
||||||
env.addReporter(fakeReporter);
|
|
||||||
env.reporter.log("message");
|
|
||||||
expect(fakeReporter.log).toHaveBeenCalledWith("message");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("equality testing", function() {
|
|
||||||
describe("with custom equality testers", function() {
|
|
||||||
var aObj, bObj, isEqual;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
env.addEqualityTester(function(a, b) {
|
|
||||||
aObj = a;
|
|
||||||
bObj = b;
|
|
||||||
return isEqual;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should call the custom equality tester with two objects for comparison", function() {
|
|
||||||
env.equals_("1", "2");
|
|
||||||
expect(aObj).toEqual("1");
|
|
||||||
expect(bObj).toEqual("2");
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when the custom equality tester returns false", function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
isEqual = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should give custom equality testers precedence", function() {
|
|
||||||
expect(env.equals_('abc', 'abc')).toBeFalsy();
|
|
||||||
var o = new Object();
|
|
||||||
expect(env.equals_(o, o)).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe("when the custom equality tester returns true", function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
isEqual = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should give custom equality testers precedence", function() {
|
|
||||||
expect(env.equals_('abc', 'def')).toBeTruthy();
|
|
||||||
expect(env.equals_(true, false)).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when the custom equality tester returns undefined", function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
isEqual = jasmine.undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should use normal equality rules", function() {
|
|
||||||
expect(env.equals_('abc', 'abc')).toBeTruthy();
|
|
||||||
expect(env.equals_('abc', 'def')).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("even if there are several", function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
env.addEqualityTester(function(a, b) { return jasmine.undefined; });
|
|
||||||
env.addEqualityTester(function(a, b) { return jasmine.undefined; });
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should use normal equality rules", function() {
|
|
||||||
expect(env.equals_('abc', 'abc')).toBeTruthy();
|
|
||||||
expect(env.equals_('abc', 'def')).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should evaluate custom equality testers in the order they are declared", function() {
|
|
||||||
isEqual = false;
|
|
||||||
env.addEqualityTester(function(a, b) { return true; });
|
|
||||||
expect(env.equals_('abc', 'abc')).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
describe('Exceptions:', function() {
|
|
||||||
var env;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
env = new jasmine.Env();
|
|
||||||
env.updateInterval = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('jasmine.formatException formats Firefox exception messages as expected', function() {
|
|
||||||
var sampleFirefoxException = {
|
|
||||||
fileName: 'foo.js',
|
|
||||||
line: '1978',
|
|
||||||
message: 'you got your foo in my bar',
|
|
||||||
name: 'A Classic Mistake'
|
|
||||||
};
|
|
||||||
|
|
||||||
var expected = 'A Classic Mistake: you got your foo in my bar in foo.js (line 1978)';
|
|
||||||
|
|
||||||
expect(jasmine.util.formatException(sampleFirefoxException)).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('jasmine.formatException formats Webkit exception messages as expected', function() {
|
|
||||||
var sampleWebkitException = {
|
|
||||||
sourceURL: 'foo.js',
|
|
||||||
lineNumber: '1978',
|
|
||||||
message: 'you got your foo in my bar',
|
|
||||||
name: 'A Classic Mistake'
|
|
||||||
};
|
|
||||||
|
|
||||||
var expected = 'A Classic Mistake: you got your foo in my bar in foo.js (line 1978)';
|
|
||||||
|
|
||||||
expect(jasmine.util.formatException(sampleWebkitException)).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle exceptions thrown, but continue', function() {
|
|
||||||
var fakeTimer = new jasmine.FakeTimer();
|
|
||||||
env.setTimeout = fakeTimer.setTimeout;
|
|
||||||
env.clearTimeout = fakeTimer.clearTimeout;
|
|
||||||
env.setInterval = fakeTimer.setInterval;
|
|
||||||
env.clearInterval = fakeTimer.clearInterval;
|
|
||||||
|
|
||||||
//we run two exception tests to make sure we continue after throwing an exception
|
|
||||||
var suite = env.describe('Suite for handles exceptions', function () {
|
|
||||||
env.it('should be a test that fails because it throws an exception', function() {
|
|
||||||
throw new Error('fake error 1');
|
|
||||||
});
|
|
||||||
|
|
||||||
env.it('should be another test that fails because it throws an exception', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
throw new Error('fake error 2');
|
|
||||||
});
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.it('should be a passing test that runs after exceptions are thrown', function() {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
env.it('should be another test that fails because it throws an exception after a wait', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
var foo = 'foo';
|
|
||||||
});
|
|
||||||
this.waits(250);
|
|
||||||
this.runs(function () {
|
|
||||||
throw new Error('fake error 3');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.it('should be a passing test that runs after exceptions are thrown from a async test', function() {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
var runner = env.currentRunner();
|
|
||||||
suite.execute();
|
|
||||||
fakeTimer.tick(2500);
|
|
||||||
|
|
||||||
var suiteResults = suite.results();
|
|
||||||
var specResults = suiteResults.getItems();
|
|
||||||
|
|
||||||
expect(suiteResults.passed()).toEqual(false);
|
|
||||||
//
|
|
||||||
expect(specResults.length).toEqual(5);
|
|
||||||
expect(specResults[0].passed()).toMatch(false);
|
|
||||||
var blockResults = specResults[0].getItems();
|
|
||||||
expect(blockResults[0].passed()).toEqual(false);
|
|
||||||
expect(blockResults[0].message).toMatch(/fake error 1/);
|
|
||||||
|
|
||||||
expect(specResults[1].passed()).toEqual(false);
|
|
||||||
var blockResults = specResults[1].getItems();
|
|
||||||
expect(blockResults[0].passed()).toEqual(false);
|
|
||||||
expect(blockResults[0].message).toMatch(/fake error 2/),
|
|
||||||
expect(blockResults[1].passed()).toEqual(true);
|
|
||||||
|
|
||||||
expect(specResults[2].passed()).toEqual(true);
|
|
||||||
|
|
||||||
expect(specResults[3].passed()).toEqual(false);
|
|
||||||
blockResults = specResults[3].getItems();
|
|
||||||
expect(blockResults[0].message).toMatch(/fake error 3/);
|
|
||||||
|
|
||||||
expect(specResults[4].passed()).toEqual(true);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
describe('jasmine.jsApiReporter', function() {
|
|
||||||
describe('results', function () {
|
|
||||||
var reporter, spec1, spec2, spec3, expectedSpec1Results, expectedSpec2Results;
|
|
||||||
var env;
|
|
||||||
var suite, nestedSuite, nestedSpec;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
env = new jasmine.Env();
|
|
||||||
env.updateInterval = 0;
|
|
||||||
|
|
||||||
suite = env.describe("top-level suite", function() {
|
|
||||||
spec1 = env.it("spec 1", function() {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
spec2 = env.it("spec 2", function() {
|
|
||||||
this.expect(true).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
nestedSuite = env.describe("nested suite", function() {
|
|
||||||
nestedSpec = env.it("nested spec", function() {
|
|
||||||
expect(true).toEqual(true);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
spec3 = env.it("spec 3", function() {
|
|
||||||
this.log('some debug message');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
reporter = new jasmine.JsApiReporter();
|
|
||||||
env.addReporter(reporter);
|
|
||||||
|
|
||||||
env.execute();
|
|
||||||
|
|
||||||
expectedSpec1Results = {
|
|
||||||
messages: spec1.results().getItems(),
|
|
||||||
result: "passed"
|
|
||||||
};
|
|
||||||
expectedSpec2Results = {
|
|
||||||
messages: spec2.results().getItems(),
|
|
||||||
result: "failed"
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
it('resultForSpec() should return the result for the given spec', function () {
|
|
||||||
expect(reporter.resultsForSpec(spec1.id)).toEqual(expectedSpec1Results);
|
|
||||||
expect(reporter.resultsForSpec(spec2.id)).toEqual(expectedSpec2Results);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('results() should return a hash of all results, indexed by spec id', function () {
|
|
||||||
expect(reporter.results()[spec1.id]).toEqual(expectedSpec1Results);
|
|
||||||
expect(reporter.results()[spec2.id]).toEqual(expectedSpec2Results);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return nested suites as children of their parents", function() {
|
|
||||||
expect(reporter.suites()).toEqual([
|
|
||||||
{ id: 0, name: 'top-level suite', type: 'suite',
|
|
||||||
children: [
|
|
||||||
{ id: 0, name: 'spec 1', type: 'spec', children: [ ] },
|
|
||||||
{ id: 1, name: 'spec 2', type: 'spec', children: [ ] },
|
|
||||||
{ id: 1, name: 'nested suite', type: 'suite',
|
|
||||||
children: [
|
|
||||||
{ id: 2, name: 'nested spec', type: 'spec', children: [ ] }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ id: 3, name: 'spec 3', type: 'spec', children: [ ] }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("#summarizeResult_", function() {
|
|
||||||
it("should summarize a passing result", function() {
|
|
||||||
var result = reporter.results()[spec1.id];
|
|
||||||
var summarizedResult = reporter.summarizeResult_(result);
|
|
||||||
expect(summarizedResult.result).toEqual('passed');
|
|
||||||
expect(summarizedResult.messages.length).toEqual(1);
|
|
||||||
expect(summarizedResult.messages[0].message).toEqual(result.messages[0].message);
|
|
||||||
expect(summarizedResult.messages[0].passed).toBeTruthy();
|
|
||||||
expect(summarizedResult.messages[0].type).toEqual('expect');
|
|
||||||
expect(summarizedResult.messages[0].text).toBeUndefined();
|
|
||||||
expect(summarizedResult.messages[0].trace.stack).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should have a stack trace for failing specs", function() {
|
|
||||||
var result = reporter.results()[spec2.id];
|
|
||||||
var summarizedResult = reporter.summarizeResult_(result);
|
|
||||||
expect(summarizedResult.result).toEqual('failed');
|
|
||||||
expect(summarizedResult.messages[0].trace.stack).toEqual(result.messages[0].trace.stack);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should have messages for specs with messages", function() {
|
|
||||||
var result = reporter.results()[spec3.id];
|
|
||||||
var summarizedResult = reporter.summarizeResult_(result);
|
|
||||||
expect(summarizedResult.result).toEqual('passed');
|
|
||||||
expect(summarizedResult.messages[0].type).toEqual('log');
|
|
||||||
expect(summarizedResult.messages[0].text).toEqual('some debug message');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,716 +0,0 @@
|
|||||||
describe("jasmine.Matchers", function() {
|
|
||||||
var env, spec;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
env = new jasmine.Env();
|
|
||||||
env.updateInterval = 0;
|
|
||||||
|
|
||||||
var suite = env.describe("suite", function() {
|
|
||||||
spec = env.it("spec", function() {
|
|
||||||
});
|
|
||||||
});
|
|
||||||
spyOn(spec, 'addMatcherResult');
|
|
||||||
});
|
|
||||||
|
|
||||||
function match(value) {
|
|
||||||
return spec.expect(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function lastResult() {
|
|
||||||
return spec.addMatcherResult.mostRecentCall.args[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
it("toEqual with primitives, objects, dates, etc.", function() {
|
|
||||||
expect(match(true).toEqual(true)).toEqual(true);
|
|
||||||
|
|
||||||
expect(match({foo:'bar'}).toEqual(null)).toEqual(false);
|
|
||||||
|
|
||||||
var functionA = function() {
|
|
||||||
return 'hi';
|
|
||||||
};
|
|
||||||
var functionB = function() {
|
|
||||||
return 'hi';
|
|
||||||
};
|
|
||||||
expect(match({foo:functionA}).toEqual({foo:functionB})).toEqual(false);
|
|
||||||
expect(match({foo:functionA}).toEqual({foo:functionA})).toEqual(true);
|
|
||||||
|
|
||||||
expect((match(false).toEqual(true))).toEqual(false);
|
|
||||||
|
|
||||||
var circularGraph = {};
|
|
||||||
circularGraph.referenceToSelf = circularGraph;
|
|
||||||
expect((match(circularGraph).toEqual(circularGraph))).toEqual(true);
|
|
||||||
|
|
||||||
expect((match(new Date(2008, 1, 3, 15, 17, 19, 1234)).toEqual(new Date(2009, 1, 3, 15, 17, 19, 1234)))).toEqual(false);
|
|
||||||
expect((match(new Date(2008, 1, 3, 15, 17, 19, 1234)).toEqual(new Date(2008, 1, 3, 15, 17, 19, 1234)))).toEqual(true);
|
|
||||||
|
|
||||||
|
|
||||||
expect(match(true).toNotEqual(false)).toEqual(true);
|
|
||||||
expect((match(true).toNotEqual(true))).toEqual(false);
|
|
||||||
|
|
||||||
expect((match(['a', 'b']).toEqual(['a', jasmine.undefined]))).toEqual(false);
|
|
||||||
expect((match(['a', 'b']).toEqual(['a', 'b', jasmine.undefined]))).toEqual(false);
|
|
||||||
|
|
||||||
expect((match(new String("cat")).toEqual("cat"))).toBe(true);
|
|
||||||
expect((match(new String("cat")).toNotEqual("cat"))).toBe(false);
|
|
||||||
|
|
||||||
expect((match(new Number(5)).toEqual(5))).toBe(true);
|
|
||||||
expect((match(new Number('5')).toEqual(5))).toBe(true);
|
|
||||||
expect((match(new Number(5)).toNotEqual(5))).toBe(false);
|
|
||||||
expect((match(new Number('5')).toNotEqual(5))).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toEqual with DOM nodes", function() {
|
|
||||||
var nodeA = document.createElement('div');
|
|
||||||
var nodeB = document.createElement('div');
|
|
||||||
expect((match(nodeA).toEqual(nodeA))).toEqual(true);
|
|
||||||
expect((match(nodeA).toEqual(nodeB))).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toEqual to build an Expectation Result", function() {
|
|
||||||
var actual = 'a';
|
|
||||||
var matcher = match(actual);
|
|
||||||
var expected = 'b';
|
|
||||||
matcher.toEqual(expected);
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toEqual");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toMatch(jasmine.pp(actual));
|
|
||||||
expect(result.message).toMatch(jasmine.pp(expected));
|
|
||||||
expect(result.expected).toEqual(expected);
|
|
||||||
expect(result.actual).toEqual(actual);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toNotEqual to build an Expectation Result", function() {
|
|
||||||
var str = 'a';
|
|
||||||
var matcher = match(str);
|
|
||||||
matcher.toNotEqual(str);
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toNotEqual");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toMatch(jasmine.pp(str));
|
|
||||||
expect(result.message).toMatch('not');
|
|
||||||
expect(result.expected).toEqual(str);
|
|
||||||
expect(result.actual).toEqual(str);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('toBe should return true only if the expected and actual items === each other', function() {
|
|
||||||
var a = {};
|
|
||||||
var b = {};
|
|
||||||
//noinspection UnnecessaryLocalVariableJS
|
|
||||||
var c = a;
|
|
||||||
expect((match(a).toBe(b))).toEqual(false);
|
|
||||||
expect((match(a).toBe(a))).toEqual(true);
|
|
||||||
expect((match(a).toBe(c))).toEqual(true);
|
|
||||||
expect((match(a).toNotBe(b))).toEqual(true);
|
|
||||||
expect((match(a).toNotBe(a))).toEqual(false);
|
|
||||||
expect((match(a).toNotBe(c))).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBe to build an ExpectationResult", function() {
|
|
||||||
var expected = 'b';
|
|
||||||
var actual = 'a';
|
|
||||||
var matcher = match(actual);
|
|
||||||
matcher.toBe(expected);
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toBe");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toMatch(jasmine.pp(actual));
|
|
||||||
expect(result.message).toMatch(jasmine.pp(expected));
|
|
||||||
expect(result.expected).toEqual(expected);
|
|
||||||
expect(result.actual).toEqual(actual);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toNotBe to build an ExpectationResult", function() {
|
|
||||||
var str = 'a';
|
|
||||||
var matcher = match(str);
|
|
||||||
matcher.toNotBe(str);
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toNotBe");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toMatch(str);
|
|
||||||
expect(result.expected).toEqual(str);
|
|
||||||
expect(result.actual).toEqual(str);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toMatch and #toNotMatch should perform regular expression matching on strings", function() {
|
|
||||||
expect((match('foobarbel').toMatch(/bar/))).toEqual(true);
|
|
||||||
expect((match('foobazbel').toMatch(/bar/))).toEqual(false);
|
|
||||||
|
|
||||||
expect((match('foobarbel').toMatch("bar"))).toEqual(true);
|
|
||||||
expect((match('foobazbel').toMatch("bar"))).toEqual(false);
|
|
||||||
|
|
||||||
expect((match('foobarbel').toNotMatch(/bar/))).toEqual(false);
|
|
||||||
expect((match('foobazbel').toNotMatch(/bar/))).toEqual(true);
|
|
||||||
|
|
||||||
expect((match('foobarbel').toNotMatch("bar"))).toEqual(false);
|
|
||||||
expect((match('foobazbel').toNotMatch("bar"))).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toMatch w/ RegExp to build an ExpectationResult", function() {
|
|
||||||
var actual = 'a';
|
|
||||||
var matcher = match(actual);
|
|
||||||
var expected = /b/;
|
|
||||||
matcher.toMatch(expected);
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toMatch");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toMatch(jasmine.pp(actual));
|
|
||||||
expect(result.message).toMatch(expected.toString());
|
|
||||||
expect(result.expected).toEqual(expected);
|
|
||||||
expect(result.actual).toEqual(actual);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toMatch w/ String to build an ExpectationResult", function() {
|
|
||||||
var actual = 'a';
|
|
||||||
var matcher = match(actual);
|
|
||||||
var expected = 'b';
|
|
||||||
matcher.toMatch(expected);
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toMatch");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toEqual("Expected 'a' to match 'b'.");
|
|
||||||
expect(result.expected).toEqual(expected);
|
|
||||||
expect(result.actual).toEqual(actual);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toNotMatch w/ RegExp to build an ExpectationResult", function() {
|
|
||||||
var actual = 'a';
|
|
||||||
var matcher = match(actual);
|
|
||||||
var expected = /a/;
|
|
||||||
matcher.toNotMatch(expected);
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toNotMatch");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toEqual("Expected 'a' to not match /a/.");
|
|
||||||
expect(result.expected).toEqual(expected);
|
|
||||||
expect(result.actual).toEqual(actual);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toNotMatch w/ String to build an ExpectationResult", function() {
|
|
||||||
var str = 'a';
|
|
||||||
var matcher = match(str);
|
|
||||||
matcher.toNotMatch(str);
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toNotMatch");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toEqual("Expected 'a' to not match 'a'.");
|
|
||||||
expect(result.expected).toEqual(str);
|
|
||||||
expect(result.actual).toEqual(str);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeDefined", function() {
|
|
||||||
expect(match('foo').toBeDefined()).toEqual(true);
|
|
||||||
expect(match(jasmine.undefined).toBeDefined()).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeDefined to build an ExpectationResult", function() {
|
|
||||||
var matcher = match(jasmine.undefined);
|
|
||||||
matcher.toBeDefined();
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toBeDefined");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toEqual('Expected undefined to be defined.');
|
|
||||||
expect(result.actual).toEqual(jasmine.undefined);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeUndefined", function() {
|
|
||||||
expect(match('foo').toBeUndefined()).toEqual(false);
|
|
||||||
expect(match(jasmine.undefined).toBeUndefined()).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeNull", function() {
|
|
||||||
expect(match(null).toBeNull()).toEqual(true);
|
|
||||||
expect(match(jasmine.undefined).toBeNull()).toEqual(false);
|
|
||||||
expect(match("foo").toBeNull()).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeNull w/ String to build an ExpectationResult", function() {
|
|
||||||
var actual = 'a';
|
|
||||||
var matcher = match(actual);
|
|
||||||
matcher.toBeNull();
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toBeNull");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toMatch(jasmine.pp(actual));
|
|
||||||
expect(result.message).toMatch('null');
|
|
||||||
expect(result.actual).toEqual(actual);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeNull w/ Object to build an ExpectationResult", function() {
|
|
||||||
var actual = {a: 'b'};
|
|
||||||
var matcher = match(actual);
|
|
||||||
matcher.toBeNull();
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toBeNull");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toMatch(jasmine.pp(actual));
|
|
||||||
expect(result.message).toMatch('null');
|
|
||||||
expect(result.actual).toEqual(actual);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeFalsy", function() {
|
|
||||||
expect(match(false).toBeFalsy()).toEqual(true);
|
|
||||||
expect(match(true).toBeFalsy()).toEqual(false);
|
|
||||||
expect(match(jasmine.undefined).toBeFalsy()).toEqual(true);
|
|
||||||
expect(match(0).toBeFalsy()).toEqual(true);
|
|
||||||
expect(match("").toBeFalsy()).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeFalsy to build an ExpectationResult", function() {
|
|
||||||
var actual = 'a';
|
|
||||||
var matcher = match(actual);
|
|
||||||
matcher.toBeFalsy();
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toBeFalsy");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toMatch(jasmine.pp(actual));
|
|
||||||
expect(result.message).toMatch('falsy');
|
|
||||||
expect(result.actual).toEqual(actual);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeTruthy", function() {
|
|
||||||
expect(match(false).toBeTruthy()).toEqual(false);
|
|
||||||
expect(match(true).toBeTruthy()).toEqual(true);
|
|
||||||
expect(match(jasmine.undefined).toBeTruthy()).toEqual(false);
|
|
||||||
expect(match(0).toBeTruthy()).toEqual(false);
|
|
||||||
expect(match("").toBeTruthy()).toEqual(false);
|
|
||||||
expect(match("hi").toBeTruthy()).toEqual(true);
|
|
||||||
expect(match(5).toBeTruthy()).toEqual(true);
|
|
||||||
expect(match({foo: 1}).toBeTruthy()).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeTruthy to build an ExpectationResult", function() {
|
|
||||||
var matcher = match(false);
|
|
||||||
matcher.toBeTruthy();
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toBeTruthy");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toEqual("Expected false to be truthy.");
|
|
||||||
expect(result.actual).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toEqual", function() {
|
|
||||||
expect(match(jasmine.undefined).toEqual(jasmine.undefined)).toEqual(true);
|
|
||||||
expect(match({foo:'bar'}).toEqual({foo:'bar'})).toEqual(true);
|
|
||||||
expect(match("foo").toEqual({bar: jasmine.undefined})).toEqual(false);
|
|
||||||
expect(match({foo: jasmine.undefined}).toEqual("goo")).toEqual(false);
|
|
||||||
expect(match({foo: {bar :jasmine.undefined}}).toEqual("goo")).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toEqual with jasmine.any()", function() {
|
|
||||||
expect(match("foo").toEqual(jasmine.any(String))).toEqual(true);
|
|
||||||
expect(match(3).toEqual(jasmine.any(Number))).toEqual(true);
|
|
||||||
expect(match("foo").toEqual(jasmine.any(Function))).toEqual(false);
|
|
||||||
expect(match("foo").toEqual(jasmine.any(Object))).toEqual(false);
|
|
||||||
expect(match({someObj:'foo'}).toEqual(jasmine.any(Object))).toEqual(true);
|
|
||||||
expect(match({someObj:'foo'}).toEqual(jasmine.any(Function))).toEqual(false);
|
|
||||||
expect(match(function() {
|
|
||||||
}).toEqual(jasmine.any(Object))).toEqual(false);
|
|
||||||
expect(match(["foo", "goo"]).toEqual(["foo", jasmine.any(String)])).toEqual(true);
|
|
||||||
expect(match(function() {
|
|
||||||
}).toEqual(jasmine.any(Function))).toEqual(true);
|
|
||||||
expect(match(["a", function() {
|
|
||||||
}]).toEqual(["a", jasmine.any(Function)])).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toEqual handles circular objects ok", function() {
|
|
||||||
expect(match({foo: "bar", baz: jasmine.undefined}).toEqual({foo: "bar", baz: jasmine.undefined})).toEqual(true);
|
|
||||||
expect(match({foo:['bar','baz','quux']}).toEqual({foo:['bar','baz','quux']})).toEqual(true);
|
|
||||||
expect(match({foo: {bar:'baz'}, quux:'corge'}).toEqual({foo:{bar:'baz'}, quux:'corge'})).toEqual(true);
|
|
||||||
|
|
||||||
var circularObject = {};
|
|
||||||
var secondCircularObject = {};
|
|
||||||
circularObject.field = circularObject;
|
|
||||||
secondCircularObject.field = secondCircularObject;
|
|
||||||
expect(match(circularObject).toEqual(secondCircularObject)).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toNotEqual as slightly surprising behavior, but is it intentional?", function() {
|
|
||||||
expect(match({x:"x", y:"y", z:"w"}).toNotEqual({x:"x", y:"y", z:"z"})).toEqual(true);
|
|
||||||
expect(match({x:"x", y:"y", w:"z"}).toNotEqual({x:"x", y:"y", z:"z"})).toEqual(true);
|
|
||||||
expect(match({x:"x", y:"y", z:"z"}).toNotEqual({w: "w", x:"x", y:"y", z:"z"})).toEqual(true);
|
|
||||||
expect(match({w: "w", x:"x", y:"y", z:"z"}).toNotEqual({x:"x", y:"y", z:"z"})).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toEqual handles arrays", function() {
|
|
||||||
expect(match([1, "A"]).toEqual([1, "A"])).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toContain and toNotContain", function() {
|
|
||||||
expect(match('ABC').toContain('A')).toEqual(true);
|
|
||||||
expect(match('ABC').toContain('X')).toEqual(false);
|
|
||||||
|
|
||||||
expect(match(['A', 'B', 'C']).toContain('A')).toEqual(true);
|
|
||||||
expect(match(['A', 'B', 'C']).toContain('F')).toEqual(false);
|
|
||||||
expect(match(['A', 'B', 'C']).toNotContain('F')).toEqual(true);
|
|
||||||
expect(match(['A', 'B', 'C']).toNotContain('A')).toEqual(false);
|
|
||||||
|
|
||||||
expect(match(['A', {some:'object'}, 'C']).toContain({some:'object'})).toEqual(true);
|
|
||||||
expect(match(['A', {some:'object'}, 'C']).toContain({some:'other object'})).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toContain to build an ExpectationResult", function() {
|
|
||||||
var actual = ['a','b','c'];
|
|
||||||
var matcher = match(actual);
|
|
||||||
var expected = 'x';
|
|
||||||
matcher.toContain(expected);
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toContain");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toMatch(jasmine.pp(actual));
|
|
||||||
expect(result.message).toMatch('contain');
|
|
||||||
expect(result.message).toMatch(jasmine.pp(expected));
|
|
||||||
expect(result.actual).toEqual(actual);
|
|
||||||
expect(result.expected).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toNotContain to build an ExpectationResult", function() {
|
|
||||||
var actual = ['a','b','c'];
|
|
||||||
var matcher = match(actual);
|
|
||||||
var expected = 'b';
|
|
||||||
matcher.toNotContain(expected);
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toNotContain");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toMatch(jasmine.pp(actual));
|
|
||||||
expect(result.message).toMatch('not contain');
|
|
||||||
expect(result.message).toMatch(jasmine.pp(expected));
|
|
||||||
expect(result.actual).toEqual(actual);
|
|
||||||
expect(result.expected).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeLessThan should pass if actual is less than expected", function() {
|
|
||||||
expect(match(37).toBeLessThan(42)).toEqual(true);
|
|
||||||
expect(match(37).toBeLessThan(-42)).toEqual(false);
|
|
||||||
expect(match(37).toBeLessThan(37)).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeLessThan to build an ExpectationResult", function() {
|
|
||||||
var actual = 3;
|
|
||||||
var matcher = match(actual);
|
|
||||||
var expected = 1;
|
|
||||||
matcher.toBeLessThan(expected);
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toBeLessThan");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toMatch(jasmine.pp(actual) + ' to be less than');
|
|
||||||
expect(result.message).toMatch(jasmine.pp(expected));
|
|
||||||
expect(result.actual).toEqual(actual);
|
|
||||||
expect(result.expected).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeGreaterThan should pass if actual is greater than expected", function() {
|
|
||||||
expect(match(37).toBeGreaterThan(42)).toEqual(false);
|
|
||||||
expect(match(37).toBeGreaterThan(-42)).toEqual(true);
|
|
||||||
expect(match(37).toBeGreaterThan(37)).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toBeGreaterThan to build an ExpectationResult", function() {
|
|
||||||
var actual = 1;
|
|
||||||
var matcher = match(actual);
|
|
||||||
var expected = 3;
|
|
||||||
matcher.toBeGreaterThan(expected);
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
|
|
||||||
expect(result.matcherName).toEqual("toBeGreaterThan");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toMatch(jasmine.pp(actual) + ' to be greater than');
|
|
||||||
expect(result.message).toMatch(jasmine.pp(expected));
|
|
||||||
expect(result.actual).toEqual(actual);
|
|
||||||
expect(result.expected).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("toThrow", function() {
|
|
||||||
var expected = match(function() {
|
|
||||||
throw new Error("Fake Error");
|
|
||||||
});
|
|
||||||
expect(expected.toThrow()).toEqual(true);
|
|
||||||
expect(expected.toThrow("Fake Error")).toEqual(true);
|
|
||||||
expect(expected.toThrow(new Error("Fake Error"))).toEqual(true);
|
|
||||||
|
|
||||||
expect(expected.toThrow("Other Error")).toEqual(false);
|
|
||||||
var result = lastResult();
|
|
||||||
expect(result.message).toMatch("Other Error");
|
|
||||||
|
|
||||||
expect(expected.toThrow(new Error("Other Error"))).toEqual(false);
|
|
||||||
result = lastResult();
|
|
||||||
expect(result.message).toMatch("Other Error");
|
|
||||||
|
|
||||||
var exception;
|
|
||||||
try {
|
|
||||||
(function () {
|
|
||||||
new jasmine.Matchers(env, 'not-a-function', spec).toThrow();
|
|
||||||
})();
|
|
||||||
} catch (e) {
|
|
||||||
exception = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(exception).toBeDefined();
|
|
||||||
expect(exception.message).toEqual('Actual is not a function');
|
|
||||||
|
|
||||||
|
|
||||||
expect(match(function() {
|
|
||||||
}).toThrow()).toEqual(false);
|
|
||||||
result = lastResult();
|
|
||||||
expect(result.message).toEqual('Expected function to throw an exception.');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe(".not.matcher", function() {
|
|
||||||
it("should invert the sense of any matcher", function() {
|
|
||||||
expect(match(37).not.toBeGreaterThan(42)).toEqual(true);
|
|
||||||
expect(match(42).not.toBeGreaterThan(37)).toEqual(false);
|
|
||||||
expect(match("abc").not.toEqual("def")).toEqual(true);
|
|
||||||
expect(match("abc").not.toEqual("abc")).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should provide an inverted default message", function() {
|
|
||||||
match(37).not.toBeGreaterThan(42);
|
|
||||||
expect(lastResult().message).toEqual("Passed.");
|
|
||||||
|
|
||||||
match(42).not.toBeGreaterThan(37);
|
|
||||||
expect(lastResult().message).toEqual("Expected 42 not to be greater than 37.");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should use the second message when the matcher sets an array of custom messages", function() {
|
|
||||||
spec.addMatchers({
|
|
||||||
custom: function() {
|
|
||||||
this.message = function() {
|
|
||||||
return ['Expected it was called.', 'Expected it wasn\'t called.'];
|
|
||||||
};
|
|
||||||
return this.actual;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
match(true).custom();
|
|
||||||
expect(lastResult().message).toEqual("Passed.");
|
|
||||||
match(false).custom();
|
|
||||||
expect(lastResult().message).toEqual("Expected it was called.");
|
|
||||||
match(true).not.custom();
|
|
||||||
expect(lastResult().message).toEqual("Expected it wasn't called.");
|
|
||||||
match(false).not.custom();
|
|
||||||
expect(lastResult().message).toEqual("Passed.");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("spy matchers >>", function() {
|
|
||||||
var TestClass;
|
|
||||||
beforeEach(function() {
|
|
||||||
TestClass = {
|
|
||||||
normalFunction: function() {
|
|
||||||
},
|
|
||||||
spyFunction: jasmine.createSpy("My spy")
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
function shouldThrowAnExceptionWhenInvokedOnANonSpy(methodName) {
|
|
||||||
return function() {
|
|
||||||
expect(function() {
|
|
||||||
match(TestClass.normalFunction)[methodName]();
|
|
||||||
}).toThrow('Expected a spy, but got Function.');
|
|
||||||
|
|
||||||
expect(function() {
|
|
||||||
match(jasmine.undefined)[methodName]();
|
|
||||||
}).toThrow('Expected a spy, but got undefined.');
|
|
||||||
|
|
||||||
expect(function() {
|
|
||||||
match({some:'object'})[methodName]();
|
|
||||||
}).toThrow('Expected a spy, but got { some : \'object\' }.');
|
|
||||||
|
|
||||||
expect(function() {
|
|
||||||
match("<b>")[methodName]();
|
|
||||||
}).toThrow('Expected a spy, but got \'<b>\'.');
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("toHaveBeenCalled", function() {
|
|
||||||
it("should pass if the spy was called", function() {
|
|
||||||
expect(match(TestClass.spyFunction).toHaveBeenCalled()).toEqual(false);
|
|
||||||
|
|
||||||
TestClass.spyFunction();
|
|
||||||
expect(match(TestClass.spyFunction).toHaveBeenCalled()).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw an exception when invoked with any arguments", function() {
|
|
||||||
expect(function() {
|
|
||||||
match(TestClass.normalFunction).toHaveBeenCalled("unwanted argument");
|
|
||||||
}).toThrow('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('toHaveBeenCalled'));
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("wasCalled", function() {
|
|
||||||
it("should alias toHaveBeenCalled", function() {
|
|
||||||
spyOn(TestClass, 'normalFunction');
|
|
||||||
|
|
||||||
TestClass.normalFunction();
|
|
||||||
|
|
||||||
expect(TestClass.normalFunction).wasCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe("wasNotCalled", function() {
|
|
||||||
it("should pass iff the spy was not called", function() {
|
|
||||||
expect(match(TestClass.spyFunction).wasNotCalled()).toEqual(true);
|
|
||||||
|
|
||||||
TestClass.spyFunction();
|
|
||||||
expect(match(TestClass.spyFunction).wasNotCalled()).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw an exception when invoked with any arguments", function() {
|
|
||||||
expect(function() {
|
|
||||||
match(TestClass.normalFunction).wasNotCalled("unwanted argument");
|
|
||||||
}).toThrow('wasNotCalled does not take arguments');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('wasNotCalled'));
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("toHaveBeenCalledWith", function() {
|
|
||||||
it('toHaveBeenCalledWith should return true if it was called with the expected args', function() {
|
|
||||||
TestClass.spyFunction('a', 'b', 'c');
|
|
||||||
expect(match(TestClass.spyFunction).toHaveBeenCalledWith('a', 'b', 'c')).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false if it was not called with the expected args', function() {
|
|
||||||
TestClass.spyFunction('a', 'b', 'c');
|
|
||||||
var expected = match(TestClass.spyFunction);
|
|
||||||
expect(expected.toHaveBeenCalledWith('c', 'b', 'a')).toEqual(false);
|
|
||||||
var result = lastResult();
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.expected).toEqual(['c', 'b', 'a']);
|
|
||||||
expect(result.actual.mostRecentCall.args).toEqual(['a', 'b', 'c']);
|
|
||||||
expect(result.message).toContain(jasmine.pp(result.expected));
|
|
||||||
expect(result.message).toContain(jasmine.pp(result.actual.mostRecentCall.args));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false if it was not called', function() {
|
|
||||||
var expected = match(TestClass.spyFunction);
|
|
||||||
expect(expected.toHaveBeenCalledWith('c', 'b', 'a')).toEqual(false);
|
|
||||||
var result = lastResult();
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.expected).toEqual(['c', 'b', 'a']);
|
|
||||||
expect(result.actual.argsForCall).toEqual([]);
|
|
||||||
expect(result.message).toContain(jasmine.pp(result.expected));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow matches across multiple calls', function() {
|
|
||||||
var expected = match(TestClass.spyFunction);
|
|
||||||
TestClass.spyFunction('a', 'b', 'c');
|
|
||||||
TestClass.spyFunction('d', 'e', 'f');
|
|
||||||
expect(expected.toHaveBeenCalledWith('a', 'b', 'c')).toEqual(true);
|
|
||||||
expect(expected.toHaveBeenCalledWith('d', 'e', 'f')).toEqual(true);
|
|
||||||
expect(expected.toHaveBeenCalledWith('x', 'y', 'z')).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('toHaveBeenCalledWith'));
|
|
||||||
|
|
||||||
describe("to build an ExpectationResult", function () {
|
|
||||||
beforeEach(function() {
|
|
||||||
var currentSuite;
|
|
||||||
var spec;
|
|
||||||
currentSuite = env.describe('default current suite', function() {
|
|
||||||
spec = env.it();
|
|
||||||
}, spec);
|
|
||||||
TestClass = { someFunction: function(a, b) {
|
|
||||||
} };
|
|
||||||
spec.spyOn(TestClass, 'someFunction');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should should handle the case of a spy", function() {
|
|
||||||
TestClass.someFunction('a', 'c');
|
|
||||||
var matcher = match(TestClass.someFunction);
|
|
||||||
matcher.toHaveBeenCalledWith('a', 'b');
|
|
||||||
|
|
||||||
var result = lastResult();
|
|
||||||
expect(result.matcherName).toEqual("toHaveBeenCalledWith");
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.message).toContain(jasmine.pp(['a', 'b']));
|
|
||||||
expect(result.message).toContain(jasmine.pp(['a', 'c']));
|
|
||||||
expect(result.actual).toEqual(TestClass.someFunction);
|
|
||||||
expect(result.expected).toEqual(['a','b']);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("wasCalledWith", function() {
|
|
||||||
it("should alias toHaveBeenCalledWith", function() {
|
|
||||||
spyOn(TestClass, 'normalFunction');
|
|
||||||
|
|
||||||
TestClass.normalFunction(123);
|
|
||||||
|
|
||||||
expect(TestClass.normalFunction).wasCalledWith(123);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("wasNotCalledWith", function() {
|
|
||||||
it('should return true if the spy was NOT called with the expected args', function() {
|
|
||||||
TestClass.spyFunction('a', 'b', 'c');
|
|
||||||
expect(match(TestClass.spyFunction).wasNotCalledWith('c', 'b', 'a')).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false if it WAS called with the expected args', function() {
|
|
||||||
TestClass.spyFunction('a', 'b', 'c');
|
|
||||||
var expected = match(TestClass.spyFunction);
|
|
||||||
expect(expected.wasNotCalledWith('a', 'b', 'c')).toEqual(false);
|
|
||||||
var result = lastResult();
|
|
||||||
expect(result.passed()).toEqual(false);
|
|
||||||
expect(result.expected).toEqual(['a', 'b', 'c']);
|
|
||||||
expect(result.actual.mostRecentCall.args).toEqual(['a', 'b', 'c']);
|
|
||||||
expect(result.message).toContain(jasmine.pp(result.expected));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true if it was not called', function() {
|
|
||||||
var expected = match(TestClass.spyFunction);
|
|
||||||
expect(expected.wasNotCalledWith('c', 'b', 'a')).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow matches across multiple calls', function() {
|
|
||||||
var expected = match(TestClass.spyFunction);
|
|
||||||
TestClass.spyFunction('a', 'b', 'c');
|
|
||||||
TestClass.spyFunction('d', 'e', 'f');
|
|
||||||
expect(expected.wasNotCalledWith('a', 'b', 'c')).toEqual(false);
|
|
||||||
expect(expected.wasNotCalledWith('d', 'e', 'f')).toEqual(false);
|
|
||||||
expect(expected.wasNotCalledWith('x', 'y', 'z')).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('wasNotCalledWith'));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
describe("MockClock", function () {
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
jasmine.Clock.useMock();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("setTimeout", function () {
|
|
||||||
it("should mock the clock when useMock is in a beforeEach", function() {
|
|
||||||
var expected = false;
|
|
||||||
setTimeout(function() {
|
|
||||||
expected = true;
|
|
||||||
}, 30000);
|
|
||||||
expect(expected).toBe(false);
|
|
||||||
jasmine.Clock.tick(30001);
|
|
||||||
expect(expected).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("setInterval", function () {
|
|
||||||
it("should mock the clock when useMock is in a beforeEach", function() {
|
|
||||||
var interval = 0;
|
|
||||||
setInterval(function() {
|
|
||||||
interval++;
|
|
||||||
}, 30000);
|
|
||||||
expect(interval).toEqual(0);
|
|
||||||
jasmine.Clock.tick(30001);
|
|
||||||
expect(interval).toEqual(1);
|
|
||||||
jasmine.Clock.tick(30001);
|
|
||||||
expect(interval).toEqual(2);
|
|
||||||
jasmine.Clock.tick(1);
|
|
||||||
expect(interval).toEqual(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("shouldn't complain if you call jasmine.Clock.useMock() more than once", function() {
|
|
||||||
jasmine.Clock.useMock();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
describe("jasmine.MultiReporter", function() {
|
|
||||||
var multiReporter, fakeReporter1, fakeReporter2;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
multiReporter = new jasmine.MultiReporter();
|
|
||||||
fakeReporter1 = jasmine.createSpyObj("fakeReporter1", ["reportSpecResults"]);
|
|
||||||
fakeReporter2 = jasmine.createSpyObj("fakeReporter2", ["reportSpecResults", "reportRunnerStarting"]);
|
|
||||||
multiReporter.addReporter(fakeReporter1);
|
|
||||||
multiReporter.addReporter(fakeReporter2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should support all the method calls that jasmine.Reporter supports", function() {
|
|
||||||
var delegate = {};
|
|
||||||
multiReporter.addReporter(delegate);
|
|
||||||
|
|
||||||
this.addMatchers({
|
|
||||||
toDelegateMethod: function(methodName) {
|
|
||||||
delegate[methodName] = jasmine.createSpy(methodName);
|
|
||||||
this.actual[methodName]("whatever argument");
|
|
||||||
|
|
||||||
return delegate[methodName].wasCalled
|
|
||||||
&& delegate[methodName].mostRecentCall.args.length == 1
|
|
||||||
&& delegate[methodName].mostRecentCall.args[0] == "whatever argument";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(multiReporter).toDelegateMethod('reportRunnerStarting');
|
|
||||||
expect(multiReporter).toDelegateMethod('reportRunnerResults');
|
|
||||||
expect(multiReporter).toDelegateMethod('reportSuiteResults');
|
|
||||||
expect(multiReporter).toDelegateMethod('reportSpecStarting');
|
|
||||||
expect(multiReporter).toDelegateMethod('reportSpecResults');
|
|
||||||
expect(multiReporter).toDelegateMethod('log');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should delegate to any and all subreporters", function() {
|
|
||||||
multiReporter.reportSpecResults('blah', 'foo');
|
|
||||||
expect(fakeReporter1.reportSpecResults).toHaveBeenCalledWith('blah', 'foo');
|
|
||||||
expect(fakeReporter2.reportSpecResults).toHaveBeenCalledWith('blah', 'foo');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should quietly skip delegating to any subreporters which lack the given method", function() {
|
|
||||||
multiReporter.reportRunnerStarting('blah', 'foo');
|
|
||||||
expect(fakeReporter2.reportRunnerStarting).toHaveBeenCalledWith('blah', 'foo');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
describe('jasmine.NestedResults', function() {
|
|
||||||
it('#addResult increments counters', function() {
|
|
||||||
// Leaf case
|
|
||||||
var results = new jasmine.NestedResults();
|
|
||||||
|
|
||||||
results.addResult(new jasmine.ExpectationResult({
|
|
||||||
matcherName: "foo", passed: true, message: 'Passed.', actual: 'bar', expected: 'bar'}
|
|
||||||
));
|
|
||||||
|
|
||||||
expect(results.getItems().length).toEqual(1);
|
|
||||||
expect(results.totalCount).toEqual(1);
|
|
||||||
expect(results.passedCount).toEqual(1);
|
|
||||||
expect(results.failedCount).toEqual(0);
|
|
||||||
|
|
||||||
results.addResult(new jasmine.ExpectationResult({
|
|
||||||
matcherName: "baz", passed: false, message: 'FAIL.', actual: "corge", expected: "quux"
|
|
||||||
}));
|
|
||||||
|
|
||||||
expect(results.getItems().length).toEqual(2);
|
|
||||||
expect(results.totalCount).toEqual(2);
|
|
||||||
expect(results.passedCount).toEqual(1);
|
|
||||||
expect(results.failedCount).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should roll up counts for nested results', function() {
|
|
||||||
// Branch case
|
|
||||||
var leafResultsOne = new jasmine.NestedResults();
|
|
||||||
leafResultsOne.addResult(new jasmine.ExpectationResult({
|
|
||||||
matcherName: "toSomething", passed: true, message: 'message', actual: '', expected:''
|
|
||||||
}));
|
|
||||||
|
|
||||||
leafResultsOne.addResult(new jasmine.ExpectationResult({
|
|
||||||
matcherName: "toSomethingElse", passed: false, message: 'message', actual: 'a', expected: 'b'
|
|
||||||
}));
|
|
||||||
|
|
||||||
var leafResultsTwo = new jasmine.NestedResults();
|
|
||||||
leafResultsTwo.addResult(new jasmine.ExpectationResult({
|
|
||||||
matcherName: "toSomething", passed: true, message: 'message', actual: '', expected: ''
|
|
||||||
}));
|
|
||||||
leafResultsTwo.addResult(new jasmine.ExpectationResult({
|
|
||||||
matcherName: "toSomethineElse", passed: false, message: 'message', actual: 'c', expected: 'd'
|
|
||||||
}));
|
|
||||||
|
|
||||||
var branchResults = new jasmine.NestedResults();
|
|
||||||
branchResults.addResult(leafResultsOne);
|
|
||||||
branchResults.addResult(leafResultsTwo);
|
|
||||||
|
|
||||||
expect(branchResults.getItems().length).toEqual(2);
|
|
||||||
expect(branchResults.totalCount).toEqual(4);
|
|
||||||
expect(branchResults.passedCount).toEqual(2);
|
|
||||||
expect(branchResults.failedCount).toEqual(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
describe("jasmine.pp", function () {
|
|
||||||
it("should wrap strings in single quotes", function() {
|
|
||||||
expect(jasmine.pp("some string")).toEqual("'some string'");
|
|
||||||
expect(jasmine.pp("som' string")).toEqual("'som' string'");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should stringify primitives properly", function() {
|
|
||||||
expect(jasmine.pp(true)).toEqual("true");
|
|
||||||
expect(jasmine.pp(false)).toEqual("false");
|
|
||||||
expect(jasmine.pp(null)).toEqual("null");
|
|
||||||
expect(jasmine.pp(jasmine.undefined)).toEqual("undefined");
|
|
||||||
expect(jasmine.pp(3)).toEqual("3");
|
|
||||||
expect(jasmine.pp(-3.14)).toEqual("-3.14");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should stringify arrays properly", function() {
|
|
||||||
expect(jasmine.pp([1, 2])).toEqual("[ 1, 2 ]");
|
|
||||||
expect(jasmine.pp([1, 'foo', {}, jasmine.undefined, null])).toEqual("[ 1, 'foo', { }, undefined, null ]");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should indicate circular array references", function() {
|
|
||||||
var array1 = [1, 2];
|
|
||||||
var array2 = [array1];
|
|
||||||
array1.push(array2);
|
|
||||||
expect(jasmine.pp(array1)).toEqual("[ 1, 2, [ <circular reference: Array> ] ]");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should stringify objects properly", function() {
|
|
||||||
expect(jasmine.pp({foo: 'bar'})).toEqual("{ foo : 'bar' }");
|
|
||||||
expect(jasmine.pp({foo:'bar', baz:3, nullValue: null, undefinedValue: jasmine.undefined})).toEqual("{ foo : 'bar', baz : 3, nullValue : null, undefinedValue : undefined }");
|
|
||||||
expect(jasmine.pp({foo: function () {
|
|
||||||
}, bar: [1, 2, 3]})).toEqual("{ foo : Function, bar : [ 1, 2, 3 ] }");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should stringify RegExp objects properly", function() {
|
|
||||||
expect(jasmine.pp(/x|y|z/)).toEqual("/x|y|z/");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should indicate circular object references", function() {
|
|
||||||
var sampleValue = {foo: 'hello'};
|
|
||||||
sampleValue.nested = sampleValue;
|
|
||||||
expect(jasmine.pp(sampleValue)).toEqual("{ foo : 'hello', nested : <circular reference: Object> }");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should indicate getters on objects as such", function() {
|
|
||||||
var sampleValue = {id: 1};
|
|
||||||
if (sampleValue.__defineGetter__) {
|
|
||||||
//not supported in IE!
|
|
||||||
sampleValue.__defineGetter__('calculatedValue', function() {
|
|
||||||
throw new Error("don't call me!");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (sampleValue.__defineGetter__) {
|
|
||||||
expect(jasmine.pp(sampleValue)).toEqual("{ id : 1, calculatedValue : <getter> }");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
expect(jasmine.pp(sampleValue)).toEqual("{ id : 1 }");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should stringify HTML nodes properly", function() {
|
|
||||||
var sampleNode = document.createElement('div');
|
|
||||||
sampleNode.innerHTML = 'foo<b>bar</b>';
|
|
||||||
expect(jasmine.pp(sampleNode)).toEqual("HTMLNode");
|
|
||||||
expect(jasmine.pp({foo: sampleNode})).toEqual("{ foo : HTMLNode }");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not do HTML escaping of strings', function() {
|
|
||||||
expect(jasmine.pp('some <b>html string</b> &', false)).toEqual('\'some <b>html string</b> &\'');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should abbreviate the global (usually window) object", function() {
|
|
||||||
expect(jasmine.pp(jasmine.getGlobal())).toEqual("<global>");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should stringify Date objects properly", function() {
|
|
||||||
var now = new Date();
|
|
||||||
expect(jasmine.pp(now)).toEqual("Date(" + now.toString() + ")");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should stringify spy objects properly", function() {
|
|
||||||
var TestObject = {
|
|
||||||
someFunction: function() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
spyOn(TestObject, 'someFunction');
|
|
||||||
expect(jasmine.pp(TestObject.someFunction)).toEqual("spy on someFunction");
|
|
||||||
|
|
||||||
expect(jasmine.pp(jasmine.createSpy("something"))).toEqual("spy on something");
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
describe("jasmine.Queue", function() {
|
|
||||||
it("should not call itself recursively, so we don't get stack overflow errors", function() {
|
|
||||||
var queue = new jasmine.Queue(new jasmine.Env());
|
|
||||||
queue.add(new jasmine.Block(null, function() {}));
|
|
||||||
queue.add(new jasmine.Block(null, function() {}));
|
|
||||||
queue.add(new jasmine.Block(null, function() {}));
|
|
||||||
queue.add(new jasmine.Block(null, function() {}));
|
|
||||||
|
|
||||||
var nestCount = 0;
|
|
||||||
var maxNestCount = 0;
|
|
||||||
var nextCallCount = 0;
|
|
||||||
queue.next_ = function() {
|
|
||||||
nestCount++;
|
|
||||||
if (nestCount > maxNestCount) maxNestCount = nestCount;
|
|
||||||
|
|
||||||
jasmine.Queue.prototype.next_.apply(queue, arguments);
|
|
||||||
nestCount--;
|
|
||||||
};
|
|
||||||
|
|
||||||
queue.start();
|
|
||||||
expect(maxNestCount).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
describe('jasmine.Reporter', function() {
|
|
||||||
var env;
|
|
||||||
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
env = new jasmine.Env();
|
|
||||||
env.updateInterval = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should get called from the test runner', function() {
|
|
||||||
env.describe('Suite for JSON Reporter with Callbacks', function () {
|
|
||||||
env.it('should be a test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
env.it('should be a failing test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(false).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
env.describe('Suite for JSON Reporter with Callbacks 2', function () {
|
|
||||||
env.it('should be a test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
var foo = 0;
|
|
||||||
var bar = 0;
|
|
||||||
var baz = 0;
|
|
||||||
|
|
||||||
env.addReporter({
|
|
||||||
reportSpecResults: function() {
|
|
||||||
foo++;
|
|
||||||
},
|
|
||||||
reportSuiteResults: function() {
|
|
||||||
bar++;
|
|
||||||
},
|
|
||||||
reportRunnerResults: function() {
|
|
||||||
baz++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var runner = env.currentRunner();
|
|
||||||
runner.execute();
|
|
||||||
|
|
||||||
expect(foo).toEqual(3); // 'foo was expected to be 3, was ' + foo);
|
|
||||||
expect(bar).toEqual(2); // 'bar was expected to be 2, was ' + bar);
|
|
||||||
expect(baz).toEqual(1); // 'baz was expected to be 1, was ' + baz);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,267 +0,0 @@
|
|||||||
describe('RunnerTest', function() {
|
|
||||||
var fakeTimer;
|
|
||||||
var env;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
env = new jasmine.Env();
|
|
||||||
env.updateInterval = 0;
|
|
||||||
|
|
||||||
fakeTimer = new jasmine.FakeTimer();
|
|
||||||
env.setTimeout = fakeTimer.setTimeout;
|
|
||||||
env.clearTimeout = fakeTimer.clearTimeout;
|
|
||||||
env.setInterval = fakeTimer.setInterval;
|
|
||||||
env.clearInterval = fakeTimer.clearInterval;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('beforeEach', function() {
|
|
||||||
it('should run before each spec for all suites', function () {
|
|
||||||
var foo;
|
|
||||||
env.beforeEach(function () {
|
|
||||||
foo = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('suite 1', function () {
|
|
||||||
env.it('test 1-1', function() {
|
|
||||||
foo++;
|
|
||||||
this.expect(foo).toEqual(1);
|
|
||||||
});
|
|
||||||
env.it('test 1-2', function() {
|
|
||||||
foo++;
|
|
||||||
this.expect(foo).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('suite 2', function () {
|
|
||||||
env.it('test 2-1', function() {
|
|
||||||
foo++;
|
|
||||||
this.expect(foo).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.currentRunner().execute();
|
|
||||||
|
|
||||||
var runnerResults = env.currentRunner().results();
|
|
||||||
expect(runnerResults.totalCount).toEqual(3);
|
|
||||||
expect(runnerResults.passedCount).toEqual(3);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should provide all specs', function () {
|
|
||||||
var foo;
|
|
||||||
env.beforeEach(function () {
|
|
||||||
foo = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('suite 1', function () {
|
|
||||||
env.it('test 1-1', function() {
|
|
||||||
foo++;
|
|
||||||
this.expect(foo).toEqual(1);
|
|
||||||
});
|
|
||||||
env.it('test 1-2', function() {
|
|
||||||
foo++;
|
|
||||||
this.expect(foo).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('suite 2', function () {
|
|
||||||
env.it('test 2-1', function() {
|
|
||||||
foo++;
|
|
||||||
this.expect(foo).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.currentRunner().execute();
|
|
||||||
|
|
||||||
|
|
||||||
expect(env.currentRunner().specs().length).toEqual(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('afterEach', function() {
|
|
||||||
it('should run after each spec for all suites', function () {
|
|
||||||
var foo = 3;
|
|
||||||
env.afterEach(function () {
|
|
||||||
foo = foo - 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('suite 1', function () {
|
|
||||||
env.it('test 1-1', function() {
|
|
||||||
this.expect(foo).toEqual(3);
|
|
||||||
});
|
|
||||||
env.it('test 1-2', function() {
|
|
||||||
this.expect(foo).toEqual(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('suite 2', function () {
|
|
||||||
env.it('test 2-1', function() {
|
|
||||||
this.expect(foo).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.currentRunner().execute();
|
|
||||||
|
|
||||||
var runnerResults = env.currentRunner().results();
|
|
||||||
expect(runnerResults.totalCount).toEqual(3);
|
|
||||||
expect(runnerResults.passedCount).toEqual(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should run child suites and specs and generate results when execute is called', function() {
|
|
||||||
env.describe('one suite description', function () {
|
|
||||||
env.it('should be a test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('another suite description', function () {
|
|
||||||
env.it('should be another test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.currentRunner().execute();
|
|
||||||
|
|
||||||
var runnerResults = env.currentRunner().results();
|
|
||||||
expect(runnerResults.totalCount).toEqual(2);
|
|
||||||
expect(runnerResults.passedCount).toEqual(1);
|
|
||||||
expect(runnerResults.failedCount).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should ignore suites that have been x\'d', function() {
|
|
||||||
env.xdescribe('one suite description', function () {
|
|
||||||
env.it('should be a test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('another suite description', function () {
|
|
||||||
env.it('should be another test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.currentRunner().execute();
|
|
||||||
|
|
||||||
var runnerResults = env.currentRunner().results();
|
|
||||||
expect(runnerResults.totalCount).toEqual(1);
|
|
||||||
expect(runnerResults.passedCount).toEqual(0);
|
|
||||||
expect(runnerResults.failedCount).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should roll up results from all specs', function() {
|
|
||||||
env.describe('one suite description', function () {
|
|
||||||
env.it('should be a test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('another suite description', function () {
|
|
||||||
env.it('should be another test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.currentRunner().execute();
|
|
||||||
|
|
||||||
var results = env.currentRunner().results();
|
|
||||||
expect(results.totalCount).toEqual(2);
|
|
||||||
expect(results.passedCount).toEqual(1);
|
|
||||||
expect(results.failedCount).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('reporting', function () {
|
|
||||||
var fakeReporter;
|
|
||||||
beforeEach(function () {
|
|
||||||
fakeReporter = jasmine.createSpyObj("fakeReporter", ["log", "reportRunnerStarting", "reportRunnerResults"]);
|
|
||||||
env.addReporter(fakeReporter);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should report runner results when the runner has completed running', function() {
|
|
||||||
env.describe('one suite description', function () {
|
|
||||||
env.it('should be a test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.describe('another suite description', function () {
|
|
||||||
env.it('should be another test', function() {
|
|
||||||
this.waits(200);
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.currentRunner().execute();
|
|
||||||
expect(fakeReporter.reportRunnerResults).not.toHaveBeenCalled();
|
|
||||||
fakeTimer.tick(200);
|
|
||||||
//This blows up the JSApiReporter.
|
|
||||||
//expect(fakeReporter.reportRunnerResults).toHaveBeenCalledWith(env.currentRunner);
|
|
||||||
expect(fakeReporter.reportRunnerResults).toHaveBeenCalled();
|
|
||||||
expect(fakeReporter.reportRunnerResults.mostRecentCall.args[0].results()).toEqual(env.currentRunner().results());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should report when the tests start running", function() {
|
|
||||||
var fakeReporter = jasmine.createSpyObj("fakeReporter", ["log", "reportRunnerStarting"]);
|
|
||||||
env.addReporter(fakeReporter);
|
|
||||||
|
|
||||||
|
|
||||||
var runner = new jasmine.Runner(env);
|
|
||||||
runner.arbitraryVariable = 'foo';
|
|
||||||
spyOn(runner.queue, 'start');
|
|
||||||
expect(fakeReporter.reportRunnerStarting).not.toHaveBeenCalled();
|
|
||||||
runner.execute();
|
|
||||||
expect(fakeReporter.reportRunnerStarting).toHaveBeenCalled();
|
|
||||||
var reportedRunner = fakeReporter.reportRunnerStarting.mostRecentCall.args[0];
|
|
||||||
expect(reportedRunner.arbitraryVariable).toEqual('foo');
|
|
||||||
expect(runner.queue.start).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when suites are nested", function() {
|
|
||||||
var suite1, suite2, suite3;
|
|
||||||
|
|
||||||
function suiteNames(suites) {
|
|
||||||
var suiteDescriptions = [];
|
|
||||||
for (var i = 0; i < suites.length; i++) {
|
|
||||||
suiteDescriptions.push(suites[i].getFullName());
|
|
||||||
}
|
|
||||||
return suiteDescriptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
suite1 = env.describe("suite 1", function() {
|
|
||||||
suite2 = env.describe("suite 2", function() {
|
|
||||||
});
|
|
||||||
});
|
|
||||||
suite3 = env.describe("suite 3", function() {});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("#suites should return a flat array of all suites, including nested suites", function() {
|
|
||||||
var suites = env.currentRunner().suites();
|
|
||||||
expect(suiteNames(suites)).toEqual([suite1.getFullName(), suite2.getFullName(), suite3.getFullName()]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("#topLevelSuites should return a flat array of all top-level suites only", function() {
|
|
||||||
var suites = env.currentRunner().topLevelSuites();
|
|
||||||
expect(suiteNames(suites)).toEqual([suite1.getFullName(), suite3.getFullName()]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
describe('Spec', function () {
|
|
||||||
var env, suite;
|
|
||||||
beforeEach(function() {
|
|
||||||
env = new jasmine.Env();
|
|
||||||
env.updateInterval = 0;
|
|
||||||
suite = new jasmine.Suite(env, 'suite 1');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('initialization', function () {
|
|
||||||
|
|
||||||
it('should raise an error if an env is not passed', function () {
|
|
||||||
try {
|
|
||||||
new jasmine.Spec();
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
expect(e.message).toEqual('jasmine.Env() required');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should raise an error if a suite is not passed', function () {
|
|
||||||
try {
|
|
||||||
new jasmine.Spec(env);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
expect(e.message).toEqual('jasmine.Suite() required');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should assign sequential ids for specs belonging to the same env', function () {
|
|
||||||
var spec1 = new jasmine.Spec(env, suite);
|
|
||||||
var spec2 = new jasmine.Spec(env, suite);
|
|
||||||
var spec3 = new jasmine.Spec(env, suite);
|
|
||||||
expect(spec1.id).toEqual(0);
|
|
||||||
expect(spec2.id).toEqual(1);
|
|
||||||
expect(spec3.id).toEqual(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getFullName returns suite & spec description', function () {
|
|
||||||
var spec = new jasmine.Spec(env, suite, 'spec 1');
|
|
||||||
expect(spec.getFullName()).toEqual('suite 1 spec 1.')
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('results', function () {
|
|
||||||
var spec, results;
|
|
||||||
beforeEach(function () {
|
|
||||||
spec = new jasmine.Spec(env, suite);
|
|
||||||
results = spec.results();
|
|
||||||
expect(results.totalCount).toEqual(0);
|
|
||||||
spec.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('results shows the total number of expectations for each spec after execution', function () {
|
|
||||||
expect(results.totalCount).toEqual(0);
|
|
||||||
spec.execute();
|
|
||||||
expect(results.totalCount).toEqual(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('results shows the number of passed expectations for each spec after execution', function () {
|
|
||||||
expect(results.passedCount).toEqual(0);
|
|
||||||
spec.execute();
|
|
||||||
expect(results.passedCount).toEqual(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('results shows the number of failed expectations for each spec after execution', function () {
|
|
||||||
spec.runs(function () {
|
|
||||||
this.expect(true).toEqual(false);
|
|
||||||
});
|
|
||||||
expect(results.failedCount).toEqual(0);
|
|
||||||
spec.execute();
|
|
||||||
expect(results.failedCount).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('results.passed', function () {
|
|
||||||
it('is true if all spec expectations pass', function () {
|
|
||||||
spec.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
spec.execute();
|
|
||||||
expect(results.passed()).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('is false if one spec expectation fails', function () {
|
|
||||||
spec.runs(function () {
|
|
||||||
this.expect(true).toEqual(false);
|
|
||||||
});
|
|
||||||
spec.execute();
|
|
||||||
expect(results.passed()).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('a spec with no expectations will return true', function () {
|
|
||||||
var specWithoutExpectations = new jasmine.Spec(env, suite);
|
|
||||||
specWithoutExpectations.runs(function() {
|
|
||||||
|
|
||||||
});
|
|
||||||
specWithoutExpectations.execute();
|
|
||||||
expect(results.passed()).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('an unexecuted spec will return true', function () {
|
|
||||||
expect(results.passed()).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("includes log messages, which may contain arbitary objects", function() {
|
|
||||||
spec.runs(function() {
|
|
||||||
this.log("here's some log message", {key: 'value'}, 123);
|
|
||||||
});
|
|
||||||
spec.execute();
|
|
||||||
var items = results.getItems();
|
|
||||||
expect(items).toEqual([
|
|
||||||
jasmine.any(jasmine.ExpectationResult),
|
|
||||||
jasmine.any(jasmine.ExpectationResult),
|
|
||||||
jasmine.any(jasmine.MessageResult)
|
|
||||||
]);
|
|
||||||
var logResult = items[2];
|
|
||||||
expect(logResult.values).toEqual(["here's some log message", {key: 'value'}, 123]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
describe('Spies', function () {
|
|
||||||
it('should replace the specified function with a spy object', function() {
|
|
||||||
var originalFunctionWasCalled = false;
|
|
||||||
var TestClass = {
|
|
||||||
someFunction: function() {
|
|
||||||
originalFunctionWasCalled = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.spyOn(TestClass, 'someFunction');
|
|
||||||
|
|
||||||
expect(TestClass.someFunction.wasCalled).toEqual(false);
|
|
||||||
expect(TestClass.someFunction.callCount).toEqual(0);
|
|
||||||
TestClass.someFunction('foo');
|
|
||||||
expect(TestClass.someFunction.wasCalled).toEqual(true);
|
|
||||||
expect(TestClass.someFunction.callCount).toEqual(1);
|
|
||||||
expect(TestClass.someFunction.mostRecentCall.args).toEqual(['foo']);
|
|
||||||
expect(TestClass.someFunction.mostRecentCall.object).toEqual(TestClass);
|
|
||||||
expect(originalFunctionWasCalled).toEqual(false);
|
|
||||||
|
|
||||||
TestClass.someFunction('bar');
|
|
||||||
expect(TestClass.someFunction.callCount).toEqual(2);
|
|
||||||
expect(TestClass.someFunction.mostRecentCall.args).toEqual(['bar']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow you to view args for a particular call', function() {
|
|
||||||
var originalFunctionWasCalled = false;
|
|
||||||
var TestClass = {
|
|
||||||
someFunction: function() {
|
|
||||||
originalFunctionWasCalled = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.spyOn(TestClass, 'someFunction');
|
|
||||||
|
|
||||||
TestClass.someFunction('foo');
|
|
||||||
TestClass.someFunction('bar');
|
|
||||||
expect(TestClass.someFunction.calls[0].args).toEqual(['foo']);
|
|
||||||
expect(TestClass.someFunction.calls[1].args).toEqual(['bar']);
|
|
||||||
expect(TestClass.someFunction.mostRecentCall.args).toEqual(['bar']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be possible to call through to the original method, or return a specific result', function() {
|
|
||||||
var originalFunctionWasCalled = false;
|
|
||||||
var passedArgs;
|
|
||||||
var passedObj;
|
|
||||||
var TestClass = {
|
|
||||||
someFunction: function() {
|
|
||||||
originalFunctionWasCalled = true;
|
|
||||||
passedArgs = arguments;
|
|
||||||
passedObj = this;
|
|
||||||
return "return value from original function";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.spyOn(TestClass, 'someFunction').andCallThrough();
|
|
||||||
var result = TestClass.someFunction('arg1', 'arg2');
|
|
||||||
expect(result).toEqual("return value from original function");
|
|
||||||
expect(originalFunctionWasCalled).toEqual(true);
|
|
||||||
expect(passedArgs).toEqual(['arg1', 'arg2']);
|
|
||||||
expect(passedObj).toEqual(TestClass);
|
|
||||||
expect(TestClass.someFunction.wasCalled).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be possible to return a specific value', function() {
|
|
||||||
var originalFunctionWasCalled = false;
|
|
||||||
var TestClass = {
|
|
||||||
someFunction: function() {
|
|
||||||
originalFunctionWasCalled = true;
|
|
||||||
return "return value from original function";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.spyOn(TestClass, 'someFunction').andReturn("some value");
|
|
||||||
originalFunctionWasCalled = false;
|
|
||||||
var result = TestClass.someFunction('arg1', 'arg2');
|
|
||||||
expect(result).toEqual("some value");
|
|
||||||
expect(originalFunctionWasCalled).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be possible to throw a specific error', function() {
|
|
||||||
var originalFunctionWasCalled = false;
|
|
||||||
var TestClass = {
|
|
||||||
someFunction: function() {
|
|
||||||
originalFunctionWasCalled = true;
|
|
||||||
return "return value from original function";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.spyOn(TestClass, 'someFunction').andThrow(new Error('fake error'));
|
|
||||||
var exception;
|
|
||||||
try {
|
|
||||||
TestClass.someFunction('arg1', 'arg2');
|
|
||||||
} catch (e) {
|
|
||||||
exception = e;
|
|
||||||
}
|
|
||||||
expect(exception.message).toEqual('fake error');
|
|
||||||
expect(originalFunctionWasCalled).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be possible to call a specified function', function() {
|
|
||||||
var originalFunctionWasCalled = false;
|
|
||||||
var fakeFunctionWasCalled = false;
|
|
||||||
var passedArgs;
|
|
||||||
var passedObj;
|
|
||||||
var TestClass = {
|
|
||||||
someFunction: function() {
|
|
||||||
originalFunctionWasCalled = true;
|
|
||||||
return "return value from original function";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.spyOn(TestClass, 'someFunction').andCallFake(function() {
|
|
||||||
fakeFunctionWasCalled = true;
|
|
||||||
passedArgs = arguments;
|
|
||||||
passedObj = this;
|
|
||||||
return "return value from fake function";
|
|
||||||
});
|
|
||||||
|
|
||||||
var result = TestClass.someFunction('arg1', 'arg2');
|
|
||||||
expect(result).toEqual("return value from fake function");
|
|
||||||
expect(originalFunctionWasCalled).toEqual(false);
|
|
||||||
expect(fakeFunctionWasCalled).toEqual(true);
|
|
||||||
expect(passedArgs).toEqual(['arg1', 'arg2']);
|
|
||||||
expect(passedObj).toEqual(TestClass);
|
|
||||||
expect(TestClass.someFunction.wasCalled).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('is torn down when this.removeAllSpies is called', function() {
|
|
||||||
var originalFunctionWasCalled = false;
|
|
||||||
var TestClass = {
|
|
||||||
someFunction: function() {
|
|
||||||
originalFunctionWasCalled = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.spyOn(TestClass, 'someFunction');
|
|
||||||
|
|
||||||
TestClass.someFunction('foo');
|
|
||||||
expect(originalFunctionWasCalled).toEqual(false);
|
|
||||||
|
|
||||||
this.removeAllSpies();
|
|
||||||
|
|
||||||
TestClass.someFunction('foo');
|
|
||||||
expect(originalFunctionWasCalled).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('calls removeAllSpies during spec finish', function() {
|
|
||||||
var test = new jasmine.Spec(new jasmine.Env(), {}, 'sample test');
|
|
||||||
|
|
||||||
this.spyOn(test, 'removeAllSpies');
|
|
||||||
|
|
||||||
test.finish();
|
|
||||||
|
|
||||||
expect(test.removeAllSpies).wasCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('throws an exception when some method is spied on twice', function() {
|
|
||||||
var TestClass = { someFunction: function() {
|
|
||||||
} };
|
|
||||||
this.spyOn(TestClass, 'someFunction');
|
|
||||||
var exception;
|
|
||||||
try {
|
|
||||||
this.spyOn(TestClass, 'someFunction');
|
|
||||||
} catch (e) {
|
|
||||||
exception = e;
|
|
||||||
}
|
|
||||||
expect(exception).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be able to reset a spy', function() {
|
|
||||||
var TestClass = { someFunction: function() {} };
|
|
||||||
this.spyOn(TestClass, 'someFunction');
|
|
||||||
|
|
||||||
expect(TestClass.someFunction).not.toHaveBeenCalled();
|
|
||||||
TestClass.someFunction();
|
|
||||||
expect(TestClass.someFunction).toHaveBeenCalled();
|
|
||||||
TestClass.someFunction.reset();
|
|
||||||
expect(TestClass.someFunction).not.toHaveBeenCalled();
|
|
||||||
expect(TestClass.someFunction.callCount).toEqual(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("createSpyObj", function() {
|
|
||||||
it("should create an object with a bunch of spy methods when you call jasmine.createSpyObj()", function() {
|
|
||||||
var spyObj = jasmine.createSpyObj('BaseName', ['method1', 'method2']);
|
|
||||||
expect(spyObj).toEqual({ method1: jasmine.any(Function), method2: jasmine.any(Function)});
|
|
||||||
expect(spyObj.method1.identity).toEqual('BaseName.method1');
|
|
||||||
expect(spyObj.method2.identity).toEqual('BaseName.method2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw if you do not pass an array argument", function() {
|
|
||||||
expect(function() {
|
|
||||||
jasmine.createSpyObj('BaseName');
|
|
||||||
}).toThrow('createSpyObj requires a non-empty array of method names to create spies for');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw if you pass an empty array argument", function() {
|
|
||||||
expect(function() {
|
|
||||||
jasmine.createSpyObj('BaseName');
|
|
||||||
}).toThrow('createSpyObj requires a non-empty array of method names to create spies for');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
describe('Suite', function() {
|
|
||||||
var fakeTimer;
|
|
||||||
var env;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
env = new jasmine.Env();
|
|
||||||
env.updateInterval = 0;
|
|
||||||
|
|
||||||
fakeTimer = new jasmine.FakeTimer();
|
|
||||||
env.setTimeout = fakeTimer.setTimeout;
|
|
||||||
env.clearTimeout = fakeTimer.clearTimeout;
|
|
||||||
env.setInterval = fakeTimer.setInterval;
|
|
||||||
env.clearInterval = fakeTimer.clearInterval;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Specs', function () {
|
|
||||||
var suite;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
suite = env.describe('Suite 1', function () {
|
|
||||||
env.it('Spec 1', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
env.it('Spec 2', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
env.describe('Suite 2', function () {
|
|
||||||
env.it('Spec 3', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
env.it('Spec 4', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('#specs should return all immediate children that are specs.', function () {
|
|
||||||
var suiteSpecs = suite.specs();
|
|
||||||
expect(suiteSpecs.length).toEqual(3);
|
|
||||||
expect(suiteSpecs[0].description).toEqual('Spec 1');
|
|
||||||
expect(suiteSpecs[1].description).toEqual('Spec 2');
|
|
||||||
expect(suiteSpecs[2].description).toEqual('Spec 4');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("#suites should return all immediate children that are suites.", function() {
|
|
||||||
var nestedSuites = suite.suites();
|
|
||||||
expect(nestedSuites.length).toEqual(1);
|
|
||||||
expect(nestedSuites[0].description).toEqual('Suite 2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("#children should return all immediate children including suites and specs.", function() {
|
|
||||||
var children = suite.children();
|
|
||||||
expect(children.length).toEqual(4);
|
|
||||||
expect(children[0].description).toEqual('Spec 1');
|
|
||||||
expect(children[1].description).toEqual('Spec 2');
|
|
||||||
expect(children[2].description).toEqual('Suite 2');
|
|
||||||
expect(children[3].description).toEqual('Spec 4');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('SpecCount', function () {
|
|
||||||
|
|
||||||
it('should keep a count of the number of specs that are run', function() {
|
|
||||||
var suite = env.describe('one suite description', function () {
|
|
||||||
env.it('should be a test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
env.it('should be another test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
env.it('should be a third test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(suite.specs().length).toEqual(3);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('specCount should be correct even with runs/waits blocks', function() {
|
|
||||||
var suite = env.describe('one suite description', function () {
|
|
||||||
env.it('should be a test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
env.it('should be another test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
this.waits(10);
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
env.it('should be a third test', function() {
|
|
||||||
this.runs(function () {
|
|
||||||
this.expect(true).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(suite.specs().length).toEqual(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,235 +0,0 @@
|
|||||||
describe("TrivialReporter", function() {
|
|
||||||
var env;
|
|
||||||
var trivialReporter;
|
|
||||||
var body;
|
|
||||||
var fakeDocument;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
env = new jasmine.Env();
|
|
||||||
env.updateInterval = 0;
|
|
||||||
|
|
||||||
body = document.createElement("body");
|
|
||||||
fakeDocument = { body: body, location: { search: "" } };
|
|
||||||
trivialReporter = new jasmine.TrivialReporter(fakeDocument);
|
|
||||||
});
|
|
||||||
|
|
||||||
function fakeSpec(name) {
|
|
||||||
return {
|
|
||||||
getFullName: function() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function findElements(divs, withClass) {
|
|
||||||
var els = [];
|
|
||||||
for (var i = 0; i < divs.length; i++) {
|
|
||||||
if (divs[i].className == withClass) els.push(divs[i]);
|
|
||||||
}
|
|
||||||
return els;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findElement(divs, withClass) {
|
|
||||||
var els = findElements(divs, withClass);
|
|
||||||
if (els.length > 0) return els[0];
|
|
||||||
throw new Error("couldn't find div with class " + withClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
it("should run only specs beginning with spec parameter", function() {
|
|
||||||
fakeDocument.location.search = "?spec=run%20this";
|
|
||||||
expect(trivialReporter.specFilter(fakeSpec("run this"))).toBeTruthy();
|
|
||||||
expect(trivialReporter.specFilter(fakeSpec("not the right spec"))).toBeFalsy();
|
|
||||||
expect(trivialReporter.specFilter(fakeSpec("not run this"))).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should display empty divs for every suite when the runner is starting", function() {
|
|
||||||
trivialReporter.reportRunnerStarting({
|
|
||||||
env: env,
|
|
||||||
suites: function() {
|
|
||||||
return [ new jasmine.Suite({}, "suite 1", null, null) ];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var divs = findElements(body.getElementsByTagName("div"), "suite");
|
|
||||||
expect(divs.length).toEqual(1);
|
|
||||||
expect(divs[0].innerHTML).toContain("suite 1");
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Matcher reporting', function () {
|
|
||||||
var getResultMessageDiv = function (body) {
|
|
||||||
var divs = body.getElementsByTagName("div");
|
|
||||||
for (var i = 0; i < divs.length; i++) {
|
|
||||||
if (divs[i].className.match(/resultMessage/)) {
|
|
||||||
return divs[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var runner, spec, fakeTimer;
|
|
||||||
beforeEach(function () {
|
|
||||||
fakeTimer = new jasmine.FakeTimer();
|
|
||||||
env.setTimeout = fakeTimer.setTimeout;
|
|
||||||
env.clearTimeout = fakeTimer.clearTimeout;
|
|
||||||
env.setInterval = fakeTimer.setInterval;
|
|
||||||
env.clearInterval = fakeTimer.clearInterval;
|
|
||||||
runner = env.currentRunner();
|
|
||||||
var suite = new jasmine.Suite(env, 'some suite');
|
|
||||||
runner.add(suite);
|
|
||||||
spec = new jasmine.Spec(env, suite, 'some spec');
|
|
||||||
suite.add(spec);
|
|
||||||
fakeDocument.location.search = "?";
|
|
||||||
env.addReporter(trivialReporter);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('toContain', function () {
|
|
||||||
it('should show actual and expected', function () {
|
|
||||||
spec.runs(function () {
|
|
||||||
this.expect('foo').toContain('bar');
|
|
||||||
});
|
|
||||||
runner.execute();
|
|
||||||
fakeTimer.tick(0);
|
|
||||||
|
|
||||||
var resultEl = getResultMessageDiv(body);
|
|
||||||
expect(resultEl.innerHTML).toMatch(/foo/);
|
|
||||||
expect(resultEl.innerHTML).toMatch(/bar/);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe("failure messages (integration)", function () {
|
|
||||||
var spec, results, expectationResult;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
results = {
|
|
||||||
passed: function() {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
getItems: function() {
|
|
||||||
}};
|
|
||||||
|
|
||||||
var suite1 = new jasmine.Suite(env, "suite 1", null, null);
|
|
||||||
|
|
||||||
spec = {
|
|
||||||
suite: suite1,
|
|
||||||
getFullName: function() {
|
|
||||||
return "foo";
|
|
||||||
},
|
|
||||||
results: function() {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
trivialReporter.reportRunnerStarting({
|
|
||||||
env: env,
|
|
||||||
suites: function() {
|
|
||||||
return [ suite1 ];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should add the failure message to the DOM (non-toEquals matchers)", function() {
|
|
||||||
expectationResult = new jasmine.ExpectationResult({
|
|
||||||
matcherName: "toBeNull", passed: false, message: "Expected 'a' to be null, but it was not"
|
|
||||||
});
|
|
||||||
|
|
||||||
spyOn(results, 'getItems').andReturn([expectationResult]);
|
|
||||||
|
|
||||||
trivialReporter.reportSpecResults(spec);
|
|
||||||
|
|
||||||
var divs = body.getElementsByTagName("div");
|
|
||||||
var errorDiv = findElement(divs, 'resultMessage fail');
|
|
||||||
expect(errorDiv.innerHTML).toEqual("Expected 'a' to be null, but it was not");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should add the failure message to the DOM (non-toEquals matchers) html escaping", function() {
|
|
||||||
expectationResult = new jasmine.ExpectationResult({
|
|
||||||
matcherName: "toBeNull", passed: false, message: "Expected '1 < 2' to <b>e null, & it was not"
|
|
||||||
});
|
|
||||||
|
|
||||||
spyOn(results, 'getItems').andReturn([expectationResult]);
|
|
||||||
|
|
||||||
trivialReporter.reportSpecResults(spec);
|
|
||||||
|
|
||||||
var divs = body.getElementsByTagName("div");
|
|
||||||
var errorDiv = findElement(divs, 'resultMessage fail');
|
|
||||||
expect(errorDiv.innerHTML).toEqual("Expected '1 < 2' to <b>e null, & it was not");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("log messages", function() {
|
|
||||||
it("should appear in the report", function() {
|
|
||||||
env.describe("suite", function() {
|
|
||||||
env.it("will have log messages", function() {
|
|
||||||
this.log("this is a", "multipart log message");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.addReporter(trivialReporter);
|
|
||||||
env.execute();
|
|
||||||
|
|
||||||
var divs = body.getElementsByTagName("div");
|
|
||||||
var errorDiv = findElement(divs, 'resultMessage log');
|
|
||||||
expect(errorDiv.innerHTML).toEqual("this is a multipart log message");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("duplicate example names", function() {
|
|
||||||
it("should report failures correctly", function() {
|
|
||||||
var suite1 = env.describe("suite", function() {
|
|
||||||
env.it("will have log messages", function() {
|
|
||||||
this.log("this one fails!");
|
|
||||||
this.expect(true).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
var suite2 = env.describe("suite", function() {
|
|
||||||
env.it("will have log messages", function() {
|
|
||||||
this.log("this one passes!");
|
|
||||||
this.expect(true).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
env.addReporter(trivialReporter);
|
|
||||||
env.execute();
|
|
||||||
|
|
||||||
var divs = body.getElementsByTagName("div");
|
|
||||||
var passedSpecDiv = findElement(divs, 'suite passed');
|
|
||||||
expect(passedSpecDiv.className).toEqual('suite passed');
|
|
||||||
expect(passedSpecDiv.innerHTML).toContain("this one passes!");
|
|
||||||
expect(passedSpecDiv.innerHTML).not.toContain("this one fails!");
|
|
||||||
|
|
||||||
var failedSpecDiv = findElement(divs, 'suite failed');
|
|
||||||
expect(failedSpecDiv.className).toEqual('suite failed');
|
|
||||||
expect(failedSpecDiv.innerHTML).toContain("this one fails!");
|
|
||||||
expect(failedSpecDiv.innerHTML).not.toContain("this one passes!");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#reportSpecStarting', function() {
|
|
||||||
var spec1;
|
|
||||||
beforeEach(function () {
|
|
||||||
env.describe("suite 1", function() {
|
|
||||||
spec1 = env.it("spec 1", function() {
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('DOES NOT log running specs by default', function() {
|
|
||||||
spyOn(trivialReporter, 'log');
|
|
||||||
|
|
||||||
trivialReporter.reportSpecStarting(spec1);
|
|
||||||
|
|
||||||
expect(trivialReporter.log).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('logs running specs when log_running_specs is true', function() {
|
|
||||||
trivialReporter.logRunningSpecs = true;
|
|
||||||
spyOn(trivialReporter, 'log');
|
|
||||||
|
|
||||||
trivialReporter.reportSpecStarting(spec1);
|
|
||||||
|
|
||||||
expect(trivialReporter.log).toHaveBeenCalledWith('>> Jasmine Running suite 1 spec 1...');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
describe("jasmine.util", function() {
|
|
||||||
describe("extend", function () {
|
|
||||||
it("should add properies to a destination object ", function() {
|
|
||||||
var destination = {baz: 'baz'};
|
|
||||||
jasmine.util.extend(destination, {
|
|
||||||
foo: 'foo', bar: 'bar'
|
|
||||||
});
|
|
||||||
expect(destination).toEqual({foo: 'foo', bar: 'bar', baz: 'baz'});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should replace properies that already exist on a destination object", function() {
|
|
||||||
var destination = {foo: 'foo'};
|
|
||||||
jasmine.util.extend(destination, {
|
|
||||||
foo: 'bar'
|
|
||||||
});
|
|
||||||
expect(destination).toEqual({foo: 'bar'});
|
|
||||||
jasmine.util.extend(destination, {
|
|
||||||
foo: null
|
|
||||||
});
|
|
||||||
expect(destination).toEqual({foo: null});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("isArray_", function() {
|
|
||||||
it("should return true if the argument is an array", function() {
|
|
||||||
expect(jasmine.isArray_([])).toBe(true);
|
|
||||||
expect(jasmine.isArray_(['a'])).toBe(true);
|
|
||||||
expect(jasmine.isArray_(new Array())).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return false if the argument is not an array", function() {
|
|
||||||
expect(jasmine.isArray_(undefined)).toBe(false);
|
|
||||||
expect(jasmine.isArray_({})).toBe(false);
|
|
||||||
expect(jasmine.isArray_(function() {})).toBe(false);
|
|
||||||
expect(jasmine.isArray_('foo')).toBe(false);
|
|
||||||
expect(jasmine.isArray_(5)).toBe(false);
|
|
||||||
expect(jasmine.isArray_(null)).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
describe('WaitsForBlock', function () {
|
|
||||||
var env, suite, timeout, spec, message, onComplete, fakeTimer;
|
|
||||||
beforeEach(function() {
|
|
||||||
env = new jasmine.Env();
|
|
||||||
env.updateInterval = 0;
|
|
||||||
suite = new jasmine.Suite(env, 'suite 1');
|
|
||||||
timeout = 1000;
|
|
||||||
spec = new jasmine.Spec(env, suite);
|
|
||||||
message = "some error message";
|
|
||||||
onComplete = jasmine.createSpy("onComplete");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('onComplete should be called if the latchFunction returns true', function () {
|
|
||||||
var latchFunction = function() {
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
|
||||||
expect(onComplete).wasNotCalled();
|
|
||||||
block.execute(onComplete);
|
|
||||||
expect(onComplete).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('latchFunction should run in same scope as spec', function () {
|
|
||||||
var result;
|
|
||||||
var latchFunction = function() {
|
|
||||||
result = this.scopedValue;
|
|
||||||
};
|
|
||||||
spec.scopedValue = 'foo';
|
|
||||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
|
||||||
block.execute(onComplete);
|
|
||||||
expect(result).toEqual('foo');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail spec and call onComplete if there is an error in the latchFunction', function() {
|
|
||||||
var latchFunction = jasmine.createSpy('latchFunction').andThrow('some error');
|
|
||||||
spyOn(spec, 'fail');
|
|
||||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
|
||||||
block.execute(onComplete);
|
|
||||||
expect(spec.fail).toHaveBeenCalledWith('some error');
|
|
||||||
expect(onComplete).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("if latchFunction returns false", function() {
|
|
||||||
var latchFunction, fakeTimer;
|
|
||||||
beforeEach(function() {
|
|
||||||
latchFunction = jasmine.createSpy('latchFunction').andReturn(false);
|
|
||||||
fakeTimer = new jasmine.FakeTimer();
|
|
||||||
env.setTimeout = fakeTimer.setTimeout;
|
|
||||||
env.clearTimeout = fakeTimer.clearTimeout;
|
|
||||||
env.setInterval = fakeTimer.setInterval;
|
|
||||||
env.clearInterval = fakeTimer.clearInterval;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('latchFunction should be retried after 100 ms', function () {
|
|
||||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
|
||||||
expect(latchFunction).wasNotCalled();
|
|
||||||
block.execute(onComplete);
|
|
||||||
expect(latchFunction.callCount).toEqual(1);
|
|
||||||
fakeTimer.tick(50);
|
|
||||||
expect(latchFunction.callCount).toEqual(1);
|
|
||||||
fakeTimer.tick(50);
|
|
||||||
expect(latchFunction.callCount).toEqual(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('onComplete should be called if latchFunction returns true before timeout', function () {
|
|
||||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
|
||||||
expect(onComplete).wasNotCalled();
|
|
||||||
block.execute(onComplete);
|
|
||||||
expect(onComplete).wasNotCalled();
|
|
||||||
latchFunction.andReturn(true);
|
|
||||||
fakeTimer.tick(100);
|
|
||||||
expect(onComplete).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('spec should fail with the passed message if the timeout is reached (and not call onComplete)', function () {
|
|
||||||
spyOn(spec, 'fail');
|
|
||||||
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
|
|
||||||
block.execute(onComplete);
|
|
||||||
expect(spec.fail).wasNotCalled();
|
|
||||||
fakeTimer.tick(timeout);
|
|
||||||
expect(spec.fail).toHaveBeenCalled();
|
|
||||||
var failMessage = spec.fail.mostRecentCall.args[0].message;
|
|
||||||
expect(failMessage).toMatch(message);
|
|
||||||
expect(onComplete).wasNotCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
/**
|
|
||||||
* Blocks are functions with executable code that make up a spec.
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @param {jasmine.Env} env
|
|
||||||
* @param {Function} func
|
|
||||||
* @param {jasmine.Spec} spec
|
|
||||||
*/
|
|
||||||
jasmine.Block = function(env, func, spec) {
|
|
||||||
this.env = env;
|
|
||||||
this.func = func;
|
|
||||||
this.spec = spec;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Block.prototype.execute = function(onComplete) {
|
|
||||||
try {
|
|
||||||
this.func.apply(this.spec);
|
|
||||||
} catch (e) {
|
|
||||||
this.spec.fail(e);
|
|
||||||
}
|
|
||||||
onComplete();
|
|
||||||
};
|
|
||||||
@@ -1,263 +0,0 @@
|
|||||||
/**
|
|
||||||
* Environment for Jasmine
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
jasmine.Env = function() {
|
|
||||||
this.currentSpec = null;
|
|
||||||
this.currentSuite = null;
|
|
||||||
this.currentRunner_ = new jasmine.Runner(this);
|
|
||||||
|
|
||||||
this.reporter = new jasmine.MultiReporter();
|
|
||||||
|
|
||||||
this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
|
|
||||||
this.lastUpdate = 0;
|
|
||||||
this.specFilter = function() {
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.nextSpecId_ = 0;
|
|
||||||
this.nextSuiteId_ = 0;
|
|
||||||
this.equalityTesters_ = [];
|
|
||||||
|
|
||||||
// wrap matchers
|
|
||||||
this.matchersClass = function() {
|
|
||||||
jasmine.Matchers.apply(this, arguments);
|
|
||||||
};
|
|
||||||
jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
|
|
||||||
|
|
||||||
jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
|
|
||||||
jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
|
|
||||||
jasmine.Env.prototype.setInterval = jasmine.setInterval;
|
|
||||||
jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns an object containing jasmine version build info, if set.
|
|
||||||
*/
|
|
||||||
jasmine.Env.prototype.version = function () {
|
|
||||||
if (jasmine.version_) {
|
|
||||||
return jasmine.version_;
|
|
||||||
} else {
|
|
||||||
throw new Error('Version not set');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns string containing jasmine version build info, if set.
|
|
||||||
*/
|
|
||||||
jasmine.Env.prototype.versionString = function() {
|
|
||||||
if (jasmine.version_) {
|
|
||||||
var version = this.version();
|
|
||||||
return version.major + "." + version.minor + "." + version.build + " revision " + version.revision;
|
|
||||||
} else {
|
|
||||||
return "version unknown";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns a sequential integer starting at 0
|
|
||||||
*/
|
|
||||||
jasmine.Env.prototype.nextSpecId = function () {
|
|
||||||
return this.nextSpecId_++;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns a sequential integer starting at 0
|
|
||||||
*/
|
|
||||||
jasmine.Env.prototype.nextSuiteId = function () {
|
|
||||||
return this.nextSuiteId_++;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a reporter to receive status updates from Jasmine.
|
|
||||||
* @param {jasmine.Reporter} reporter An object which will receive status updates.
|
|
||||||
*/
|
|
||||||
jasmine.Env.prototype.addReporter = function(reporter) {
|
|
||||||
this.reporter.addReporter(reporter);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Env.prototype.execute = function() {
|
|
||||||
this.currentRunner_.execute();
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Env.prototype.describe = function(description, specDefinitions) {
|
|
||||||
var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
|
|
||||||
|
|
||||||
var parentSuite = this.currentSuite;
|
|
||||||
if (parentSuite) {
|
|
||||||
parentSuite.add(suite);
|
|
||||||
} else {
|
|
||||||
this.currentRunner_.add(suite);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currentSuite = suite;
|
|
||||||
|
|
||||||
var declarationError = null;
|
|
||||||
try {
|
|
||||||
specDefinitions.call(suite);
|
|
||||||
} catch(e) {
|
|
||||||
declarationError = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currentSuite = parentSuite;
|
|
||||||
|
|
||||||
if (declarationError) {
|
|
||||||
this.it("encountered a declaration exception", function() {
|
|
||||||
throw declarationError;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return suite;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
|
|
||||||
if (this.currentSuite) {
|
|
||||||
this.currentSuite.beforeEach(beforeEachFunction);
|
|
||||||
} else {
|
|
||||||
this.currentRunner_.beforeEach(beforeEachFunction);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Env.prototype.currentRunner = function () {
|
|
||||||
return this.currentRunner_;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Env.prototype.afterEach = function(afterEachFunction) {
|
|
||||||
if (this.currentSuite) {
|
|
||||||
this.currentSuite.afterEach(afterEachFunction);
|
|
||||||
} else {
|
|
||||||
this.currentRunner_.afterEach(afterEachFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
|
|
||||||
return {
|
|
||||||
execute: function() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Env.prototype.it = function(description, func) {
|
|
||||||
var spec = new jasmine.Spec(this, this.currentSuite, description);
|
|
||||||
this.currentSuite.add(spec);
|
|
||||||
this.currentSpec = spec;
|
|
||||||
|
|
||||||
if (func) {
|
|
||||||
spec.runs(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
return spec;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Env.prototype.xit = function(desc, func) {
|
|
||||||
return {
|
|
||||||
id: this.nextSpecId(),
|
|
||||||
runs: function() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
|
|
||||||
if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.__Jasmine_been_here_before__ = b;
|
|
||||||
b.__Jasmine_been_here_before__ = a;
|
|
||||||
|
|
||||||
var hasKey = function(obj, keyName) {
|
|
||||||
return obj != null && obj[keyName] !== jasmine.undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var property in b) {
|
|
||||||
if (!hasKey(a, property) && hasKey(b, property)) {
|
|
||||||
mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (property in a) {
|
|
||||||
if (!hasKey(b, property) && hasKey(a, property)) {
|
|
||||||
mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (property in b) {
|
|
||||||
if (property == '__Jasmine_been_here_before__') continue;
|
|
||||||
if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
|
|
||||||
mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
|
|
||||||
mismatchValues.push("arrays were not the same length");
|
|
||||||
}
|
|
||||||
|
|
||||||
delete a.__Jasmine_been_here_before__;
|
|
||||||
delete b.__Jasmine_been_here_before__;
|
|
||||||
return (mismatchKeys.length == 0 && mismatchValues.length == 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
|
|
||||||
mismatchKeys = mismatchKeys || [];
|
|
||||||
mismatchValues = mismatchValues || [];
|
|
||||||
|
|
||||||
for (var i = 0; i < this.equalityTesters_.length; i++) {
|
|
||||||
var equalityTester = this.equalityTesters_[i];
|
|
||||||
var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
|
|
||||||
if (result !== jasmine.undefined) return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a === b) return true;
|
|
||||||
|
|
||||||
if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
|
|
||||||
return (a == jasmine.undefined && b == jasmine.undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
|
|
||||||
return a === b;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a instanceof Date && b instanceof Date) {
|
|
||||||
return a.getTime() == b.getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a instanceof jasmine.Matchers.Any) {
|
|
||||||
return a.matches(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b instanceof jasmine.Matchers.Any) {
|
|
||||||
return b.matches(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jasmine.isString_(a) && jasmine.isString_(b)) {
|
|
||||||
return (a == b);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
|
|
||||||
return (a == b);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof a === "object" && typeof b === "object") {
|
|
||||||
return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Straight check
|
|
||||||
return (a === b);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Env.prototype.contains_ = function(haystack, needle) {
|
|
||||||
if (jasmine.isArray_(haystack)) {
|
|
||||||
for (var i = 0; i < haystack.length; i++) {
|
|
||||||
if (this.equals_(haystack[i], needle)) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return haystack.indexOf(needle) >= 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
|
|
||||||
this.equalityTesters_.push(equalityTester);
|
|
||||||
};
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
/** JavaScript API reporter.
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
jasmine.JsApiReporter = function() {
|
|
||||||
this.started = false;
|
|
||||||
this.finished = false;
|
|
||||||
this.suites_ = [];
|
|
||||||
this.results_ = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
|
|
||||||
this.started = true;
|
|
||||||
var suites = runner.topLevelSuites();
|
|
||||||
for (var i = 0; i < suites.length; i++) {
|
|
||||||
var suite = suites[i];
|
|
||||||
this.suites_.push(this.summarize_(suite));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.JsApiReporter.prototype.suites = function() {
|
|
||||||
return this.suites_;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
|
|
||||||
var isSuite = suiteOrSpec instanceof jasmine.Suite;
|
|
||||||
var summary = {
|
|
||||||
id: suiteOrSpec.id,
|
|
||||||
name: suiteOrSpec.description,
|
|
||||||
type: isSuite ? 'suite' : 'spec',
|
|
||||||
children: []
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isSuite) {
|
|
||||||
var children = suiteOrSpec.children();
|
|
||||||
for (var i = 0; i < children.length; i++) {
|
|
||||||
summary.children.push(this.summarize_(children[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return summary;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.JsApiReporter.prototype.results = function() {
|
|
||||||
return this.results_;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
|
|
||||||
return this.results_[specId];
|
|
||||||
};
|
|
||||||
|
|
||||||
//noinspection JSUnusedLocalSymbols
|
|
||||||
jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
|
|
||||||
this.finished = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
//noinspection JSUnusedLocalSymbols
|
|
||||||
jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
|
|
||||||
};
|
|
||||||
|
|
||||||
//noinspection JSUnusedLocalSymbols
|
|
||||||
jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
|
|
||||||
this.results_[spec.id] = {
|
|
||||||
messages: spec.results().getItems(),
|
|
||||||
result: spec.results().failedCount > 0 ? "failed" : "passed"
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
//noinspection JSUnusedLocalSymbols
|
|
||||||
jasmine.JsApiReporter.prototype.log = function(str) {
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
|
|
||||||
var results = {};
|
|
||||||
for (var i = 0; i < specIds.length; i++) {
|
|
||||||
var specId = specIds[i];
|
|
||||||
results[specId] = this.summarizeResult_(this.results_[specId]);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
|
|
||||||
var summaryMessages = [];
|
|
||||||
var messagesLength = result.messages.length;
|
|
||||||
for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
|
|
||||||
var resultMessage = result.messages[messageIndex];
|
|
||||||
summaryMessages.push({
|
|
||||||
text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
|
|
||||||
passed: resultMessage.passed ? resultMessage.passed() : true,
|
|
||||||
type: resultMessage.type,
|
|
||||||
message: resultMessage.message,
|
|
||||||
trace: {
|
|
||||||
stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
result : result.result,
|
|
||||||
messages : summaryMessages
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1,336 +0,0 @@
|
|||||||
/**
|
|
||||||
* @constructor
|
|
||||||
* @param {jasmine.Env} env
|
|
||||||
* @param actual
|
|
||||||
* @param {jasmine.Spec} spec
|
|
||||||
*/
|
|
||||||
jasmine.Matchers = function(env, actual, spec, opt_isNot) {
|
|
||||||
this.env = env;
|
|
||||||
this.actual = actual;
|
|
||||||
this.spec = spec;
|
|
||||||
this.isNot = opt_isNot || false;
|
|
||||||
this.reportWasCalled_ = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// todo: @deprecated as of Jasmine 0.11, remove soon [xw]
|
|
||||||
jasmine.Matchers.pp = function(str) {
|
|
||||||
throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
|
|
||||||
};
|
|
||||||
|
|
||||||
// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
|
|
||||||
jasmine.Matchers.prototype.report = function(result, failing_message, details) {
|
|
||||||
throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
|
|
||||||
for (var methodName in prototype) {
|
|
||||||
if (methodName == 'report') continue;
|
|
||||||
var orig = prototype[methodName];
|
|
||||||
matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
|
|
||||||
return function() {
|
|
||||||
var matcherArgs = jasmine.util.argsToArray(arguments);
|
|
||||||
var result = matcherFunction.apply(this, arguments);
|
|
||||||
|
|
||||||
if (this.isNot) {
|
|
||||||
result = !result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.reportWasCalled_) return result;
|
|
||||||
|
|
||||||
var message;
|
|
||||||
if (!result) {
|
|
||||||
if (this.message) {
|
|
||||||
message = this.message.apply(this, arguments);
|
|
||||||
if (jasmine.isArray_(message)) {
|
|
||||||
message = message[this.isNot ? 1 : 0];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
|
|
||||||
message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
|
|
||||||
if (matcherArgs.length > 0) {
|
|
||||||
for (var i = 0; i < matcherArgs.length; i++) {
|
|
||||||
if (i > 0) message += ",";
|
|
||||||
message += " " + jasmine.pp(matcherArgs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
message += ".";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var expectationResult = new jasmine.ExpectationResult({
|
|
||||||
matcherName: matcherName,
|
|
||||||
passed: result,
|
|
||||||
expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
|
|
||||||
actual: this.actual,
|
|
||||||
message: message
|
|
||||||
});
|
|
||||||
this.spec.addMatcherResult(expectationResult);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* toBe: compares the actual to the expected using ===
|
|
||||||
* @param expected
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toBe = function(expected) {
|
|
||||||
return this.actual === expected;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* toNotBe: compares the actual to the expected using !==
|
|
||||||
* @param expected
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toNotBe = function(expected) {
|
|
||||||
return this.actual !== expected;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
|
|
||||||
*
|
|
||||||
* @param expected
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toEqual = function(expected) {
|
|
||||||
return this.env.equals_(this.actual, expected);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
|
|
||||||
* @param expected
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toNotEqual = function(expected) {
|
|
||||||
return !this.env.equals_(this.actual, expected);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes
|
|
||||||
* a pattern or a String.
|
|
||||||
*
|
|
||||||
* @param expected
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toMatch = function(expected) {
|
|
||||||
return new RegExp(expected).test(this.actual);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
|
|
||||||
* @param expected
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toNotMatch = function(expected) {
|
|
||||||
return !(new RegExp(expected).test(this.actual));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that compares the actual to jasmine.undefined.
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toBeDefined = function() {
|
|
||||||
return (this.actual !== jasmine.undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that compares the actual to jasmine.undefined.
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toBeUndefined = function() {
|
|
||||||
return (this.actual === jasmine.undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that compares the actual to null.
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toBeNull = function() {
|
|
||||||
return (this.actual === null);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that boolean not-nots the actual.
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toBeTruthy = function() {
|
|
||||||
return !!this.actual;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that boolean nots the actual.
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toBeFalsy = function() {
|
|
||||||
return !this.actual;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
|
|
||||||
jasmine.Matchers.prototype.wasCalled = function() {
|
|
||||||
return this.toHaveBeenCalled();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that checks to see if the actual, a Jasmine spy, was called.
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toHaveBeenCalled = function() {
|
|
||||||
if (arguments.length > 0) {
|
|
||||||
throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!jasmine.isSpy(this.actual)) {
|
|
||||||
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.message = function() {
|
|
||||||
return "Expected spy " + this.actual.identity + " to have been called.";
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.actual.wasCalled;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that checks to see if the actual, a Jasmine spy, was not called.
|
|
||||||
*
|
|
||||||
* @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.wasNotCalled = function() {
|
|
||||||
if (arguments.length > 0) {
|
|
||||||
throw new Error('wasNotCalled does not take arguments');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!jasmine.isSpy(this.actual)) {
|
|
||||||
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.message = function() {
|
|
||||||
return "Expected spy " + this.actual.identity + " to not have been called.";
|
|
||||||
};
|
|
||||||
|
|
||||||
return !this.actual.wasCalled;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
|
|
||||||
jasmine.Matchers.prototype.wasCalledWith = function() {
|
|
||||||
return this.toHaveBeenCalledWith.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
|
|
||||||
var expectedArgs = jasmine.util.argsToArray(arguments);
|
|
||||||
if (!jasmine.isSpy(this.actual)) {
|
|
||||||
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
|
|
||||||
}
|
|
||||||
this.message = function() {
|
|
||||||
if (this.actual.callCount == 0) {
|
|
||||||
return "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
|
|
||||||
} else {
|
|
||||||
return "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.env.contains_(this.actual.argsForCall, expectedArgs);
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
|
|
||||||
jasmine.Matchers.prototype.wasNotCalledWith = function() {
|
|
||||||
var expectedArgs = jasmine.util.argsToArray(arguments);
|
|
||||||
if (!jasmine.isSpy(this.actual)) {
|
|
||||||
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.message = function() {
|
|
||||||
return "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was";
|
|
||||||
};
|
|
||||||
|
|
||||||
return !this.env.contains_(this.actual.argsForCall, expectedArgs);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that checks that the expected item is an element in the actual Array.
|
|
||||||
*
|
|
||||||
* @param {Object} expected
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toContain = function(expected) {
|
|
||||||
return this.env.contains_(this.actual, expected);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that checks that the expected item is NOT an element in the actual Array.
|
|
||||||
*
|
|
||||||
* @param {Object} expected
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toNotContain = function(expected) {
|
|
||||||
return !this.env.contains_(this.actual, expected);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Matchers.prototype.toBeLessThan = function(expected) {
|
|
||||||
return this.actual < expected;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
|
|
||||||
return this.actual > expected;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matcher that checks that the expected exception was thrown by the actual.
|
|
||||||
*
|
|
||||||
* @param {String} expected
|
|
||||||
*/
|
|
||||||
jasmine.Matchers.prototype.toThrow = function(expected) {
|
|
||||||
var result = false;
|
|
||||||
var exception;
|
|
||||||
if (typeof this.actual != 'function') {
|
|
||||||
throw new Error('Actual is not a function');
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
this.actual();
|
|
||||||
} catch (e) {
|
|
||||||
exception = e;
|
|
||||||
}
|
|
||||||
if (exception) {
|
|
||||||
result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.message = function() {
|
|
||||||
if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
|
|
||||||
return ["Expected function to throw", expected.message || expected, ", but it threw", exception.message || exception].join(' ');
|
|
||||||
} else {
|
|
||||||
return "Expected function to throw an exception.";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Matchers.Any = function(expectedClass) {
|
|
||||||
this.expectedClass = expectedClass;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Matchers.Any.prototype.matches = function(other) {
|
|
||||||
if (this.expectedClass == String) {
|
|
||||||
return typeof other == 'string' || other instanceof String;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.expectedClass == Number) {
|
|
||||||
return typeof other == 'number' || other instanceof Number;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.expectedClass == Function) {
|
|
||||||
return typeof other == 'function' || other instanceof Function;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.expectedClass == Object) {
|
|
||||||
return typeof other == 'object';
|
|
||||||
}
|
|
||||||
|
|
||||||
return other instanceof this.expectedClass;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Matchers.Any.prototype.toString = function() {
|
|
||||||
return '<jasmine.any(' + this.expectedClass + ')>';
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/**
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
jasmine.MultiReporter = function() {
|
|
||||||
this.subReporters_ = [];
|
|
||||||
};
|
|
||||||
jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
|
|
||||||
|
|
||||||
jasmine.MultiReporter.prototype.addReporter = function(reporter) {
|
|
||||||
this.subReporters_.push(reporter);
|
|
||||||
};
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
var functionNames = [
|
|
||||||
"reportRunnerStarting",
|
|
||||||
"reportRunnerResults",
|
|
||||||
"reportSuiteResults",
|
|
||||||
"reportSpecStarting",
|
|
||||||
"reportSpecResults",
|
|
||||||
"log"
|
|
||||||
];
|
|
||||||
for (var i = 0; i < functionNames.length; i++) {
|
|
||||||
var functionName = functionNames[i];
|
|
||||||
jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
|
|
||||||
return function() {
|
|
||||||
for (var j = 0; j < this.subReporters_.length; j++) {
|
|
||||||
var subReporter = this.subReporters_[j];
|
|
||||||
if (subReporter[functionName]) {
|
|
||||||
subReporter[functionName].apply(subReporter, arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})(functionName);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
/**
|
|
||||||
* Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
jasmine.NestedResults = function() {
|
|
||||||
/**
|
|
||||||
* The total count of results
|
|
||||||
*/
|
|
||||||
this.totalCount = 0;
|
|
||||||
/**
|
|
||||||
* Number of passed results
|
|
||||||
*/
|
|
||||||
this.passedCount = 0;
|
|
||||||
/**
|
|
||||||
* Number of failed results
|
|
||||||
*/
|
|
||||||
this.failedCount = 0;
|
|
||||||
/**
|
|
||||||
* Was this suite/spec skipped?
|
|
||||||
*/
|
|
||||||
this.skipped = false;
|
|
||||||
/**
|
|
||||||
* @ignore
|
|
||||||
*/
|
|
||||||
this.items_ = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Roll up the result counts.
|
|
||||||
*
|
|
||||||
* @param result
|
|
||||||
*/
|
|
||||||
jasmine.NestedResults.prototype.rollupCounts = function(result) {
|
|
||||||
this.totalCount += result.totalCount;
|
|
||||||
this.passedCount += result.passedCount;
|
|
||||||
this.failedCount += result.failedCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a log message.
|
|
||||||
* @param values Array of message parts which will be concatenated later.
|
|
||||||
*/
|
|
||||||
jasmine.NestedResults.prototype.log = function(values) {
|
|
||||||
this.items_.push(new jasmine.MessageResult(values));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the results: message & results.
|
|
||||||
*/
|
|
||||||
jasmine.NestedResults.prototype.getItems = function() {
|
|
||||||
return this.items_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a result, tracking counts (total, passed, & failed)
|
|
||||||
* @param {jasmine.ExpectationResult|jasmine.NestedResults} result
|
|
||||||
*/
|
|
||||||
jasmine.NestedResults.prototype.addResult = function(result) {
|
|
||||||
if (result.type != 'log') {
|
|
||||||
if (result.items_) {
|
|
||||||
this.rollupCounts(result);
|
|
||||||
} else {
|
|
||||||
this.totalCount++;
|
|
||||||
if (result.passed()) {
|
|
||||||
this.passedCount++;
|
|
||||||
} else {
|
|
||||||
this.failedCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.items_.push(result);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {Boolean} True if <b>everything</b> below passed
|
|
||||||
*/
|
|
||||||
jasmine.NestedResults.prototype.passed = function() {
|
|
||||||
return this.passedCount === this.totalCount;
|
|
||||||
};
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
/**
|
|
||||||
* Base class for pretty printing for expectation results.
|
|
||||||
*/
|
|
||||||
jasmine.PrettyPrinter = function() {
|
|
||||||
this.ppNestLevel_ = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats a value in a nice, human-readable string.
|
|
||||||
*
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
jasmine.PrettyPrinter.prototype.format = function(value) {
|
|
||||||
if (this.ppNestLevel_ > 40) {
|
|
||||||
throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ppNestLevel_++;
|
|
||||||
try {
|
|
||||||
if (value === jasmine.undefined) {
|
|
||||||
this.emitScalar('undefined');
|
|
||||||
} else if (value === null) {
|
|
||||||
this.emitScalar('null');
|
|
||||||
} else if (value === jasmine.getGlobal()) {
|
|
||||||
this.emitScalar('<global>');
|
|
||||||
} else if (value instanceof jasmine.Matchers.Any) {
|
|
||||||
this.emitScalar(value.toString());
|
|
||||||
} else if (typeof value === 'string') {
|
|
||||||
this.emitString(value);
|
|
||||||
} else if (jasmine.isSpy(value)) {
|
|
||||||
this.emitScalar("spy on " + value.identity);
|
|
||||||
} else if (value instanceof RegExp) {
|
|
||||||
this.emitScalar(value.toString());
|
|
||||||
} else if (typeof value === 'function') {
|
|
||||||
this.emitScalar('Function');
|
|
||||||
} else if (typeof value.nodeType === 'number') {
|
|
||||||
this.emitScalar('HTMLNode');
|
|
||||||
} else if (value instanceof Date) {
|
|
||||||
this.emitScalar('Date(' + value + ')');
|
|
||||||
} else if (value.__Jasmine_been_here_before__) {
|
|
||||||
this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
|
|
||||||
} else if (jasmine.isArray_(value) || typeof value == 'object') {
|
|
||||||
value.__Jasmine_been_here_before__ = true;
|
|
||||||
if (jasmine.isArray_(value)) {
|
|
||||||
this.emitArray(value);
|
|
||||||
} else {
|
|
||||||
this.emitObject(value);
|
|
||||||
}
|
|
||||||
delete value.__Jasmine_been_here_before__;
|
|
||||||
} else {
|
|
||||||
this.emitScalar(value.toString());
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
this.ppNestLevel_--;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
|
|
||||||
for (var property in obj) {
|
|
||||||
if (property == '__Jasmine_been_here_before__') continue;
|
|
||||||
fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) != null) : false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
|
|
||||||
jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
|
|
||||||
jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
|
|
||||||
jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
|
|
||||||
|
|
||||||
jasmine.StringPrettyPrinter = function() {
|
|
||||||
jasmine.PrettyPrinter.call(this);
|
|
||||||
|
|
||||||
this.string = '';
|
|
||||||
};
|
|
||||||
jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
|
|
||||||
|
|
||||||
jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
|
|
||||||
this.append(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
|
|
||||||
this.append("'" + value + "'");
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
|
|
||||||
this.append('[ ');
|
|
||||||
for (var i = 0; i < array.length; i++) {
|
|
||||||
if (i > 0) {
|
|
||||||
this.append(', ');
|
|
||||||
}
|
|
||||||
this.format(array[i]);
|
|
||||||
}
|
|
||||||
this.append(' ]');
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
|
|
||||||
var self = this;
|
|
||||||
this.append('{ ');
|
|
||||||
var first = true;
|
|
||||||
|
|
||||||
this.iterateObject(obj, function(property, isGetter) {
|
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
self.append(', ');
|
|
||||||
}
|
|
||||||
|
|
||||||
self.append(property);
|
|
||||||
self.append(' : ');
|
|
||||||
if (isGetter) {
|
|
||||||
self.append('<getter>');
|
|
||||||
} else {
|
|
||||||
self.format(obj[property]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.append(' }');
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.StringPrettyPrinter.prototype.append = function(value) {
|
|
||||||
this.string += value;
|
|
||||||
};
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
jasmine.Queue = function(env) {
|
|
||||||
this.env = env;
|
|
||||||
this.blocks = [];
|
|
||||||
this.running = false;
|
|
||||||
this.index = 0;
|
|
||||||
this.offset = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Queue.prototype.addBefore = function(block) {
|
|
||||||
this.blocks.unshift(block);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Queue.prototype.add = function(block) {
|
|
||||||
this.blocks.push(block);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Queue.prototype.insertNext = function(block) {
|
|
||||||
this.blocks.splice((this.index + this.offset + 1), 0, block);
|
|
||||||
this.offset++;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Queue.prototype.start = function(onComplete) {
|
|
||||||
this.running = true;
|
|
||||||
this.onComplete = onComplete;
|
|
||||||
this.next_();
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Queue.prototype.isRunning = function() {
|
|
||||||
return this.running;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Queue.LOOP_DONT_RECURSE = true;
|
|
||||||
|
|
||||||
jasmine.Queue.prototype.next_ = function() {
|
|
||||||
var self = this;
|
|
||||||
var goAgain = true;
|
|
||||||
|
|
||||||
while (goAgain) {
|
|
||||||
goAgain = false;
|
|
||||||
|
|
||||||
if (self.index < self.blocks.length) {
|
|
||||||
var calledSynchronously = true;
|
|
||||||
var completedSynchronously = false;
|
|
||||||
|
|
||||||
var onComplete = function () {
|
|
||||||
if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
|
|
||||||
completedSynchronously = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.offset = 0;
|
|
||||||
self.index++;
|
|
||||||
|
|
||||||
var now = new Date().getTime();
|
|
||||||
if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
|
|
||||||
self.env.lastUpdate = now;
|
|
||||||
self.env.setTimeout(function() {
|
|
||||||
self.next_();
|
|
||||||
}, 0);
|
|
||||||
} else {
|
|
||||||
if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
|
|
||||||
goAgain = true;
|
|
||||||
} else {
|
|
||||||
self.next_();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.blocks[self.index].execute(onComplete);
|
|
||||||
|
|
||||||
calledSynchronously = false;
|
|
||||||
if (completedSynchronously) {
|
|
||||||
onComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
self.running = false;
|
|
||||||
if (self.onComplete) {
|
|
||||||
self.onComplete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Queue.prototype.results = function() {
|
|
||||||
var results = new jasmine.NestedResults();
|
|
||||||
for (var i = 0; i < this.blocks.length; i++) {
|
|
||||||
if (this.blocks[i].results) {
|
|
||||||
results.addResult(this.blocks[i].results());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
/** No-op base class for Jasmine reporters.
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
jasmine.Reporter = function() {
|
|
||||||
};
|
|
||||||
|
|
||||||
//noinspection JSUnusedLocalSymbols
|
|
||||||
jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
|
|
||||||
};
|
|
||||||
|
|
||||||
//noinspection JSUnusedLocalSymbols
|
|
||||||
jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
|
|
||||||
};
|
|
||||||
|
|
||||||
//noinspection JSUnusedLocalSymbols
|
|
||||||
jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
|
|
||||||
};
|
|
||||||
|
|
||||||
//noinspection JSUnusedLocalSymbols
|
|
||||||
jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
|
|
||||||
};
|
|
||||||
|
|
||||||
//noinspection JSUnusedLocalSymbols
|
|
||||||
jasmine.Reporter.prototype.reportSpecResults = function(spec) {
|
|
||||||
};
|
|
||||||
|
|
||||||
//noinspection JSUnusedLocalSymbols
|
|
||||||
jasmine.Reporter.prototype.log = function(str) {
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/**
|
|
||||||
* Runner
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @param {jasmine.Env} env
|
|
||||||
*/
|
|
||||||
jasmine.Runner = function(env) {
|
|
||||||
var self = this;
|
|
||||||
self.env = env;
|
|
||||||
self.queue = new jasmine.Queue(env);
|
|
||||||
self.before_ = [];
|
|
||||||
self.after_ = [];
|
|
||||||
self.suites_ = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Runner.prototype.execute = function() {
|
|
||||||
var self = this;
|
|
||||||
if (self.env.reporter.reportRunnerStarting) {
|
|
||||||
self.env.reporter.reportRunnerStarting(this);
|
|
||||||
}
|
|
||||||
self.queue.start(function () {
|
|
||||||
self.finishCallback();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
|
|
||||||
beforeEachFunction.typeName = 'beforeEach';
|
|
||||||
this.before_.splice(0,0,beforeEachFunction);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
|
|
||||||
afterEachFunction.typeName = 'afterEach';
|
|
||||||
this.after_.splice(0,0,afterEachFunction);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
jasmine.Runner.prototype.finishCallback = function() {
|
|
||||||
this.env.reporter.reportRunnerResults(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Runner.prototype.addSuite = function(suite) {
|
|
||||||
this.suites_.push(suite);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Runner.prototype.add = function(block) {
|
|
||||||
if (block instanceof jasmine.Suite) {
|
|
||||||
this.addSuite(block);
|
|
||||||
}
|
|
||||||
this.queue.add(block);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Runner.prototype.specs = function () {
|
|
||||||
var suites = this.suites();
|
|
||||||
var specs = [];
|
|
||||||
for (var i = 0; i < suites.length; i++) {
|
|
||||||
specs = specs.concat(suites[i].specs());
|
|
||||||
}
|
|
||||||
return specs;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Runner.prototype.suites = function() {
|
|
||||||
return this.suites_;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Runner.prototype.topLevelSuites = function() {
|
|
||||||
var topLevelSuites = [];
|
|
||||||
for (var i = 0; i < this.suites_.length; i++) {
|
|
||||||
if (!this.suites_[i].parentSuite) {
|
|
||||||
topLevelSuites.push(this.suites_[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return topLevelSuites;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Runner.prototype.results = function() {
|
|
||||||
return this.queue.results();
|
|
||||||
};
|
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
/**
|
|
||||||
* Internal representation of a Jasmine specification, or test.
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @param {jasmine.Env} env
|
|
||||||
* @param {jasmine.Suite} suite
|
|
||||||
* @param {String} description
|
|
||||||
*/
|
|
||||||
jasmine.Spec = function(env, suite, description) {
|
|
||||||
if (!env) {
|
|
||||||
throw new Error('jasmine.Env() required');
|
|
||||||
}
|
|
||||||
if (!suite) {
|
|
||||||
throw new Error('jasmine.Suite() required');
|
|
||||||
}
|
|
||||||
var spec = this;
|
|
||||||
spec.id = env.nextSpecId ? env.nextSpecId() : null;
|
|
||||||
spec.env = env;
|
|
||||||
spec.suite = suite;
|
|
||||||
spec.description = description;
|
|
||||||
spec.queue = new jasmine.Queue(env);
|
|
||||||
|
|
||||||
spec.afterCallbacks = [];
|
|
||||||
spec.spies_ = [];
|
|
||||||
|
|
||||||
spec.results_ = new jasmine.NestedResults();
|
|
||||||
spec.results_.description = description;
|
|
||||||
spec.matchersClass = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.getFullName = function() {
|
|
||||||
return this.suite.getFullName() + ' ' + this.description + '.';
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.results = function() {
|
|
||||||
return this.results_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All parameters are pretty-printed and concatenated together, then written to the spec's output.
|
|
||||||
*
|
|
||||||
* Be careful not to leave calls to <code>jasmine.log</code> in production code.
|
|
||||||
*/
|
|
||||||
jasmine.Spec.prototype.log = function() {
|
|
||||||
return this.results_.log(arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.runs = function (func) {
|
|
||||||
var block = new jasmine.Block(this.env, func, this);
|
|
||||||
this.addToQueue(block);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.addToQueue = function (block) {
|
|
||||||
if (this.queue.isRunning()) {
|
|
||||||
this.queue.insertNext(block);
|
|
||||||
} else {
|
|
||||||
this.queue.add(block);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {jasmine.ExpectationResult} result
|
|
||||||
*/
|
|
||||||
jasmine.Spec.prototype.addMatcherResult = function(result) {
|
|
||||||
this.results_.addResult(result);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.expect = function(actual) {
|
|
||||||
var positive = new (this.getMatchersClass_())(this.env, actual, this);
|
|
||||||
positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
|
|
||||||
return positive;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.waits = function(timeout) {
|
|
||||||
var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
|
|
||||||
this.addToQueue(waitsFunc);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.waitsFor = function(timeout, latchFunction, timeoutMessage) {
|
|
||||||
var waitsForFunc = new jasmine.WaitsForBlock(this.env, timeout, latchFunction, timeoutMessage, this);
|
|
||||||
this.addToQueue(waitsForFunc);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.fail = function (e) {
|
|
||||||
var expectationResult = new jasmine.ExpectationResult({
|
|
||||||
passed: false,
|
|
||||||
message: e ? jasmine.util.formatException(e) : 'Exception'
|
|
||||||
});
|
|
||||||
this.results_.addResult(expectationResult);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.getMatchersClass_ = function() {
|
|
||||||
return this.matchersClass || this.env.matchersClass;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
|
|
||||||
var parent = this.getMatchersClass_();
|
|
||||||
var newMatchersClass = function() {
|
|
||||||
parent.apply(this, arguments);
|
|
||||||
};
|
|
||||||
jasmine.util.inherit(newMatchersClass, parent);
|
|
||||||
jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
|
|
||||||
this.matchersClass = newMatchersClass;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.finishCallback = function() {
|
|
||||||
this.env.reporter.reportSpecResults(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.finish = function(onComplete) {
|
|
||||||
this.removeAllSpies();
|
|
||||||
this.finishCallback();
|
|
||||||
if (onComplete) {
|
|
||||||
onComplete();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.after = function(doAfter) {
|
|
||||||
if (this.queue.isRunning()) {
|
|
||||||
this.queue.add(new jasmine.Block(this.env, doAfter, this));
|
|
||||||
} else {
|
|
||||||
this.afterCallbacks.unshift(doAfter);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.execute = function(onComplete) {
|
|
||||||
var spec = this;
|
|
||||||
if (!spec.env.specFilter(spec)) {
|
|
||||||
spec.results_.skipped = true;
|
|
||||||
spec.finish(onComplete);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.env.reporter.reportSpecStarting(this);
|
|
||||||
|
|
||||||
spec.env.currentSpec = spec;
|
|
||||||
|
|
||||||
spec.addBeforesAndAftersToQueue();
|
|
||||||
|
|
||||||
spec.queue.start(function () {
|
|
||||||
spec.finish(onComplete);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
|
|
||||||
var runner = this.env.currentRunner();
|
|
||||||
var i;
|
|
||||||
|
|
||||||
for (var suite = this.suite; suite; suite = suite.parentSuite) {
|
|
||||||
for (i = 0; i < suite.before_.length; i++) {
|
|
||||||
this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (i = 0; i < runner.before_.length; i++) {
|
|
||||||
this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
|
|
||||||
}
|
|
||||||
for (i = 0; i < this.afterCallbacks.length; i++) {
|
|
||||||
this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
|
|
||||||
}
|
|
||||||
for (suite = this.suite; suite; suite = suite.parentSuite) {
|
|
||||||
for (i = 0; i < suite.after_.length; i++) {
|
|
||||||
this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (i = 0; i < runner.after_.length; i++) {
|
|
||||||
this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.explodes = function() {
|
|
||||||
throw 'explodes function should not have been called';
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
|
|
||||||
if (obj == jasmine.undefined) {
|
|
||||||
throw "spyOn could not find an object to spy upon for " + methodName + "()";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
|
|
||||||
throw methodName + '() method does not exist';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
|
|
||||||
throw new Error(methodName + ' has already been spied upon');
|
|
||||||
}
|
|
||||||
|
|
||||||
var spyObj = jasmine.createSpy(methodName);
|
|
||||||
|
|
||||||
this.spies_.push(spyObj);
|
|
||||||
spyObj.baseObj = obj;
|
|
||||||
spyObj.methodName = methodName;
|
|
||||||
spyObj.originalValue = obj[methodName];
|
|
||||||
|
|
||||||
obj[methodName] = spyObj;
|
|
||||||
|
|
||||||
return spyObj;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Spec.prototype.removeAllSpies = function() {
|
|
||||||
for (var i = 0; i < this.spies_.length; i++) {
|
|
||||||
var spy = this.spies_[i];
|
|
||||||
spy.baseObj[spy.methodName] = spy.originalValue;
|
|
||||||
}
|
|
||||||
this.spies_ = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
/**
|
|
||||||
* Internal representation of a Jasmine suite.
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @param {jasmine.Env} env
|
|
||||||
* @param {String} description
|
|
||||||
* @param {Function} specDefinitions
|
|
||||||
* @param {jasmine.Suite} parentSuite
|
|
||||||
*/
|
|
||||||
jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
|
|
||||||
var self = this;
|
|
||||||
self.id = env.nextSuiteId ? env.nextSuiteId() : null;
|
|
||||||
self.description = description;
|
|
||||||
self.queue = new jasmine.Queue(env);
|
|
||||||
self.parentSuite = parentSuite;
|
|
||||||
self.env = env;
|
|
||||||
self.before_ = [];
|
|
||||||
self.after_ = [];
|
|
||||||
self.children_ = [];
|
|
||||||
self.suites_ = [];
|
|
||||||
self.specs_ = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Suite.prototype.getFullName = function() {
|
|
||||||
var fullName = this.description;
|
|
||||||
for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
|
|
||||||
fullName = parentSuite.description + ' ' + fullName;
|
|
||||||
}
|
|
||||||
return fullName;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Suite.prototype.finish = function(onComplete) {
|
|
||||||
this.env.reporter.reportSuiteResults(this);
|
|
||||||
this.finished = true;
|
|
||||||
if (typeof(onComplete) == 'function') {
|
|
||||||
onComplete();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
|
|
||||||
beforeEachFunction.typeName = 'beforeEach';
|
|
||||||
this.before_.unshift(beforeEachFunction);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
|
|
||||||
afterEachFunction.typeName = 'afterEach';
|
|
||||||
this.after_.unshift(afterEachFunction);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Suite.prototype.results = function() {
|
|
||||||
return this.queue.results();
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Suite.prototype.add = function(suiteOrSpec) {
|
|
||||||
this.children_.push(suiteOrSpec);
|
|
||||||
if (suiteOrSpec instanceof jasmine.Suite) {
|
|
||||||
this.suites_.push(suiteOrSpec);
|
|
||||||
this.env.currentRunner().addSuite(suiteOrSpec);
|
|
||||||
} else {
|
|
||||||
this.specs_.push(suiteOrSpec);
|
|
||||||
}
|
|
||||||
this.queue.add(suiteOrSpec);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Suite.prototype.specs = function() {
|
|
||||||
return this.specs_;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Suite.prototype.suites = function() {
|
|
||||||
return this.suites_;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Suite.prototype.children = function() {
|
|
||||||
return this.children_;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.Suite.prototype.execute = function(onComplete) {
|
|
||||||
var self = this;
|
|
||||||
this.queue.start(function () {
|
|
||||||
self.finish(onComplete);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
jasmine.WaitsBlock = function(env, timeout, spec) {
|
|
||||||
this.timeout = timeout;
|
|
||||||
jasmine.Block.call(this, env, null, spec);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
|
|
||||||
|
|
||||||
jasmine.WaitsBlock.prototype.execute = function (onComplete) {
|
|
||||||
this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
|
|
||||||
this.env.setTimeout(function () {
|
|
||||||
onComplete();
|
|
||||||
}, this.timeout);
|
|
||||||
};
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
|
|
||||||
this.timeout = timeout;
|
|
||||||
this.latchFunction = latchFunction;
|
|
||||||
this.message = message;
|
|
||||||
this.totalTimeSpentWaitingForLatch = 0;
|
|
||||||
jasmine.Block.call(this, env, null, spec);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
|
|
||||||
|
|
||||||
jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 100;
|
|
||||||
|
|
||||||
jasmine.WaitsForBlock.prototype.execute = function (onComplete) {
|
|
||||||
var self = this;
|
|
||||||
self.env.reporter.log('>> Jasmine waiting for ' + (self.message || 'something to happen'));
|
|
||||||
var latchFunctionResult;
|
|
||||||
try {
|
|
||||||
latchFunctionResult = self.latchFunction.apply(self.spec);
|
|
||||||
} catch (e) {
|
|
||||||
self.spec.fail(e);
|
|
||||||
onComplete();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (latchFunctionResult) {
|
|
||||||
onComplete();
|
|
||||||
} else if (self.totalTimeSpentWaitingForLatch >= self.timeout) {
|
|
||||||
var message = 'timed out after ' + self.timeout + ' msec waiting for ' + (self.message || 'something to happen');
|
|
||||||
self.spec.fail({
|
|
||||||
name: 'timeout',
|
|
||||||
message: message
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
self.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
|
|
||||||
self.env.setTimeout(function () { self.execute(onComplete); }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,582 +0,0 @@
|
|||||||
/**
|
|
||||||
* Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
|
|
||||||
*
|
|
||||||
* @namespace
|
|
||||||
*/
|
|
||||||
var jasmine = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
jasmine.unimplementedMethod_ = function() {
|
|
||||||
throw new Error("unimplemented method");
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
|
|
||||||
* a plain old variable and may be redefined by somebody else.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
jasmine.undefined = jasmine.___undefined___;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default interval for event loop yields. Small values here may result in slow test running. Zero means no updates until all tests have completed.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
jasmine.DEFAULT_UPDATE_INTERVAL = 250;
|
|
||||||
|
|
||||||
jasmine.getGlobal = function() {
|
|
||||||
function getGlobal() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
return getGlobal();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows for bound functions to be compared. Internal use only.
|
|
||||||
*
|
|
||||||
* @ignore
|
|
||||||
* @private
|
|
||||||
* @param base {Object} bound 'this' for the function
|
|
||||||
* @param name {Function} function to find
|
|
||||||
*/
|
|
||||||
jasmine.bindOriginal_ = function(base, name) {
|
|
||||||
var original = base[name];
|
|
||||||
if (original.apply) {
|
|
||||||
return function() {
|
|
||||||
return original.apply(base, arguments);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// IE support
|
|
||||||
return jasmine.getGlobal()[name];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
|
|
||||||
jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
|
|
||||||
jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
|
|
||||||
jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
|
|
||||||
|
|
||||||
jasmine.MessageResult = function(values) {
|
|
||||||
this.type = 'log';
|
|
||||||
this.values = values;
|
|
||||||
this.trace = new Error(); // todo: test better
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.MessageResult.prototype.toString = function() {
|
|
||||||
var text = "";
|
|
||||||
for(var i = 0; i < this.values.length; i++) {
|
|
||||||
if (i > 0) text += " ";
|
|
||||||
if (jasmine.isString_(this.values[i])) {
|
|
||||||
text += this.values[i];
|
|
||||||
} else {
|
|
||||||
text += jasmine.pp(this.values[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.ExpectationResult = function(params) {
|
|
||||||
this.type = 'expect';
|
|
||||||
this.matcherName = params.matcherName;
|
|
||||||
this.passed_ = params.passed;
|
|
||||||
this.expected = params.expected;
|
|
||||||
this.actual = params.actual;
|
|
||||||
|
|
||||||
this.message = this.passed_ ? 'Passed.' : params.message;
|
|
||||||
this.trace = this.passed_ ? '' : new Error(this.message);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.ExpectationResult.prototype.toString = function () {
|
|
||||||
return this.message;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.ExpectationResult.prototype.passed = function () {
|
|
||||||
return this.passed_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the Jasmine environment. Ensures one gets created
|
|
||||||
*/
|
|
||||||
jasmine.getEnv = function() {
|
|
||||||
return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ignore
|
|
||||||
* @private
|
|
||||||
* @param value
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
jasmine.isArray_ = function(value) {
|
|
||||||
return jasmine.isA_("Array", value);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ignore
|
|
||||||
* @private
|
|
||||||
* @param value
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
jasmine.isString_ = function(value) {
|
|
||||||
return jasmine.isA_("String", value);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ignore
|
|
||||||
* @private
|
|
||||||
* @param value
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
jasmine.isNumber_ = function(value) {
|
|
||||||
return jasmine.isA_("Number", value);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ignore
|
|
||||||
* @private
|
|
||||||
* @param {String} typeName
|
|
||||||
* @param value
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
jasmine.isA_ = function(typeName, value) {
|
|
||||||
return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pretty printer for expecations. Takes any object and turns it into a human-readable string.
|
|
||||||
*
|
|
||||||
* @param value {Object} an object to be outputted
|
|
||||||
* @returns {String}
|
|
||||||
*/
|
|
||||||
jasmine.pp = function(value) {
|
|
||||||
var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
|
|
||||||
stringPrettyPrinter.format(value);
|
|
||||||
return stringPrettyPrinter.string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the object is a DOM Node.
|
|
||||||
*
|
|
||||||
* @param {Object} obj object to check
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
jasmine.isDomNode = function(obj) {
|
|
||||||
return obj['nodeType'] > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* // don't care about which function is passed in, as long as it's a function
|
|
||||||
* expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
|
|
||||||
*
|
|
||||||
* @param {Class} clazz
|
|
||||||
* @returns matchable object of the type clazz
|
|
||||||
*/
|
|
||||||
jasmine.any = function(clazz) {
|
|
||||||
return new jasmine.Matchers.Any(clazz);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
|
|
||||||
*
|
|
||||||
* Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine
|
|
||||||
* expectation syntax. Spies can be checked if they were called or not and what the calling params were.
|
|
||||||
*
|
|
||||||
* A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
|
|
||||||
*
|
|
||||||
* Spies are torn down at the end of every spec.
|
|
||||||
*
|
|
||||||
* Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* // a stub
|
|
||||||
* var myStub = jasmine.createSpy('myStub'); // can be used anywhere
|
|
||||||
*
|
|
||||||
* // spy example
|
|
||||||
* var foo = {
|
|
||||||
* not: function(bool) { return !bool; }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* // actual foo.not will not be called, execution stops
|
|
||||||
* spyOn(foo, 'not');
|
|
||||||
|
|
||||||
// foo.not spied upon, execution will continue to implementation
|
|
||||||
* spyOn(foo, 'not').andCallThrough();
|
|
||||||
*
|
|
||||||
* // fake example
|
|
||||||
* var foo = {
|
|
||||||
* not: function(bool) { return !bool; }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* // foo.not(val) will return val
|
|
||||||
* spyOn(foo, 'not').andCallFake(function(value) {return value;});
|
|
||||||
*
|
|
||||||
* // mock example
|
|
||||||
* foo.not(7 == 7);
|
|
||||||
* expect(foo.not).toHaveBeenCalled();
|
|
||||||
* expect(foo.not).toHaveBeenCalledWith(true);
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @see spyOn, jasmine.createSpy, jasmine.createSpyObj
|
|
||||||
* @param {String} name
|
|
||||||
*/
|
|
||||||
jasmine.Spy = function(name) {
|
|
||||||
/**
|
|
||||||
* The name of the spy, if provided.
|
|
||||||
*/
|
|
||||||
this.identity = name || 'unknown';
|
|
||||||
/**
|
|
||||||
* Is this Object a spy?
|
|
||||||
*/
|
|
||||||
this.isSpy = true;
|
|
||||||
/**
|
|
||||||
* The actual function this spy stubs.
|
|
||||||
*/
|
|
||||||
this.plan = function() {
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Tracking of the most recent call to the spy.
|
|
||||||
* @example
|
|
||||||
* var mySpy = jasmine.createSpy('foo');
|
|
||||||
* mySpy(1, 2);
|
|
||||||
* mySpy.mostRecentCall.args = [1, 2];
|
|
||||||
*/
|
|
||||||
this.mostRecentCall = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds arguments for each call to the spy, indexed by call count
|
|
||||||
* @example
|
|
||||||
* var mySpy = jasmine.createSpy('foo');
|
|
||||||
* mySpy(1, 2);
|
|
||||||
* mySpy(7, 8);
|
|
||||||
* mySpy.mostRecentCall.args = [7, 8];
|
|
||||||
* mySpy.argsForCall[0] = [1, 2];
|
|
||||||
* mySpy.argsForCall[1] = [7, 8];
|
|
||||||
*/
|
|
||||||
this.argsForCall = [];
|
|
||||||
this.calls = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells a spy to call through to the actual implemenatation.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* var foo = {
|
|
||||||
* bar: function() { // do some stuff }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* // defining a spy on an existing property: foo.bar
|
|
||||||
* spyOn(foo, 'bar').andCallThrough();
|
|
||||||
*/
|
|
||||||
jasmine.Spy.prototype.andCallThrough = function() {
|
|
||||||
this.plan = this.originalValue;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For setting the return value of a spy.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* // defining a spy from scratch: foo() returns 'baz'
|
|
||||||
* var foo = jasmine.createSpy('spy on foo').andReturn('baz');
|
|
||||||
*
|
|
||||||
* // defining a spy on an existing property: foo.bar() returns 'baz'
|
|
||||||
* spyOn(foo, 'bar').andReturn('baz');
|
|
||||||
*
|
|
||||||
* @param {Object} value
|
|
||||||
*/
|
|
||||||
jasmine.Spy.prototype.andReturn = function(value) {
|
|
||||||
this.plan = function() {
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For throwing an exception when a spy is called.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
|
|
||||||
* var foo = jasmine.createSpy('spy on foo').andThrow('baz');
|
|
||||||
*
|
|
||||||
* // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
|
|
||||||
* spyOn(foo, 'bar').andThrow('baz');
|
|
||||||
*
|
|
||||||
* @param {String} exceptionMsg
|
|
||||||
*/
|
|
||||||
jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
|
|
||||||
this.plan = function() {
|
|
||||||
throw exceptionMsg;
|
|
||||||
};
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls an alternate implementation when a spy is called.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* var baz = function() {
|
|
||||||
* // do some stuff, return something
|
|
||||||
* }
|
|
||||||
* // defining a spy from scratch: foo() calls the function baz
|
|
||||||
* var foo = jasmine.createSpy('spy on foo').andCall(baz);
|
|
||||||
*
|
|
||||||
* // defining a spy on an existing property: foo.bar() calls an anonymnous function
|
|
||||||
* spyOn(foo, 'bar').andCall(function() { return 'baz';} );
|
|
||||||
*
|
|
||||||
* @param {Function} fakeFunc
|
|
||||||
*/
|
|
||||||
jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
|
|
||||||
this.plan = fakeFunc;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets all of a spy's the tracking variables so that it can be used again.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* spyOn(foo, 'bar');
|
|
||||||
*
|
|
||||||
* foo.bar();
|
|
||||||
*
|
|
||||||
* expect(foo.bar.callCount).toEqual(1);
|
|
||||||
*
|
|
||||||
* foo.bar.reset();
|
|
||||||
*
|
|
||||||
* expect(foo.bar.callCount).toEqual(0);
|
|
||||||
*/
|
|
||||||
jasmine.Spy.prototype.reset = function() {
|
|
||||||
this.wasCalled = false;
|
|
||||||
this.callCount = 0;
|
|
||||||
this.argsForCall = [];
|
|
||||||
this.calls = [];
|
|
||||||
this.mostRecentCall = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.createSpy = function(name) {
|
|
||||||
|
|
||||||
var spyObj = function() {
|
|
||||||
spyObj.wasCalled = true;
|
|
||||||
spyObj.callCount++;
|
|
||||||
var args = jasmine.util.argsToArray(arguments);
|
|
||||||
spyObj.mostRecentCall.object = this;
|
|
||||||
spyObj.mostRecentCall.args = args;
|
|
||||||
spyObj.argsForCall.push(args);
|
|
||||||
spyObj.calls.push({object: this, args: args});
|
|
||||||
return spyObj.plan.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
var spy = new jasmine.Spy(name);
|
|
||||||
|
|
||||||
for (var prop in spy) {
|
|
||||||
spyObj[prop] = spy[prop];
|
|
||||||
}
|
|
||||||
|
|
||||||
spyObj.reset();
|
|
||||||
|
|
||||||
return spyObj;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether an object is a spy.
|
|
||||||
*
|
|
||||||
* @param {jasmine.Spy|Object} putativeSpy
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
jasmine.isSpy = function(putativeSpy) {
|
|
||||||
return putativeSpy && putativeSpy.isSpy;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something
|
|
||||||
* large in one call.
|
|
||||||
*
|
|
||||||
* @param {String} baseName name of spy class
|
|
||||||
* @param {Array} methodNames array of names of methods to make spies
|
|
||||||
*/
|
|
||||||
jasmine.createSpyObj = function(baseName, methodNames) {
|
|
||||||
if (!jasmine.isArray_(methodNames) || methodNames.length == 0) {
|
|
||||||
throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
|
|
||||||
}
|
|
||||||
var obj = {};
|
|
||||||
for (var i = 0; i < methodNames.length; i++) {
|
|
||||||
obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All parameters are pretty-printed and concatenated together, then written to the current spec's output.
|
|
||||||
*
|
|
||||||
* Be careful not to leave calls to <code>jasmine.log</code> in production code.
|
|
||||||
*/
|
|
||||||
jasmine.log = function() {
|
|
||||||
var spec = jasmine.getEnv().currentSpec;
|
|
||||||
spec.log.apply(spec, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that installs a spy on an existing object's method name. Used within a Spec to create a spy.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* // spy example
|
|
||||||
* var foo = {
|
|
||||||
* not: function(bool) { return !bool; }
|
|
||||||
* }
|
|
||||||
* spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
|
|
||||||
*
|
|
||||||
* @see jasmine.createSpy
|
|
||||||
* @param obj
|
|
||||||
* @param methodName
|
|
||||||
* @returns a Jasmine spy that can be chained with all spy methods
|
|
||||||
*/
|
|
||||||
var spyOn = function(obj, methodName) {
|
|
||||||
return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a Jasmine spec that will be added to the current suite.
|
|
||||||
*
|
|
||||||
* // TODO: pending tests
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* it('should be true', function() {
|
|
||||||
* expect(true).toEqual(true);
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* @param {String} desc description of this specification
|
|
||||||
* @param {Function} func defines the preconditions and expectations of the spec
|
|
||||||
*/
|
|
||||||
var it = function(desc, func) {
|
|
||||||
return jasmine.getEnv().it(desc, func);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a <em>disabled</em> Jasmine spec.
|
|
||||||
*
|
|
||||||
* A convenience method that allows existing specs to be disabled temporarily during development.
|
|
||||||
*
|
|
||||||
* @param {String} desc description of this specification
|
|
||||||
* @param {Function} func defines the preconditions and expectations of the spec
|
|
||||||
*/
|
|
||||||
var xit = function(desc, func) {
|
|
||||||
return jasmine.getEnv().xit(desc, func);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a chain for a Jasmine expectation.
|
|
||||||
*
|
|
||||||
* It is passed an Object that is the actual value and should chain to one of the many
|
|
||||||
* jasmine.Matchers functions.
|
|
||||||
*
|
|
||||||
* @param {Object} actual Actual value to test against and expected value
|
|
||||||
*/
|
|
||||||
var expect = function(actual) {
|
|
||||||
return jasmine.getEnv().currentSpec.expect(actual);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
|
|
||||||
*
|
|
||||||
* @param {Function} func Function that defines part of a jasmine spec.
|
|
||||||
*/
|
|
||||||
var runs = function(func) {
|
|
||||||
jasmine.getEnv().currentSpec.runs(func);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits for a timeout before moving to the next runs()-defined block.
|
|
||||||
* @param {Number} timeout
|
|
||||||
*/
|
|
||||||
var waits = function(timeout) {
|
|
||||||
jasmine.getEnv().currentSpec.waits(timeout);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits for the latchFunction to return true before proceeding to the next runs()-defined block.
|
|
||||||
*
|
|
||||||
* @param {Number} timeout
|
|
||||||
* @param {Function} latchFunction
|
|
||||||
* @param {String} message
|
|
||||||
*/
|
|
||||||
var waitsFor = function(timeout, latchFunction, message) {
|
|
||||||
jasmine.getEnv().currentSpec.waitsFor(timeout, latchFunction, message);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A function that is called before each spec in a suite.
|
|
||||||
*
|
|
||||||
* Used for spec setup, including validating assumptions.
|
|
||||||
*
|
|
||||||
* @param {Function} beforeEachFunction
|
|
||||||
*/
|
|
||||||
var beforeEach = function(beforeEachFunction) {
|
|
||||||
jasmine.getEnv().beforeEach(beforeEachFunction);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A function that is called after each spec in a suite.
|
|
||||||
*
|
|
||||||
* Used for restoring any state that is hijacked during spec execution.
|
|
||||||
*
|
|
||||||
* @param {Function} afterEachFunction
|
|
||||||
*/
|
|
||||||
var afterEach = function(afterEachFunction) {
|
|
||||||
jasmine.getEnv().afterEach(afterEachFunction);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a suite of specifications.
|
|
||||||
*
|
|
||||||
* Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
|
|
||||||
* are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
|
|
||||||
* of setup in some tests.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* // TODO: a simple suite
|
|
||||||
*
|
|
||||||
* // TODO: a simple suite with a nested describe block
|
|
||||||
*
|
|
||||||
* @param {String} description A string, usually the class under test.
|
|
||||||
* @param {Function} specDefinitions function that defines several specs.
|
|
||||||
*/
|
|
||||||
var describe = function(description, specDefinitions) {
|
|
||||||
return jasmine.getEnv().describe(description, specDefinitions);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
|
|
||||||
*
|
|
||||||
* @param {String} description A string, usually the class under test.
|
|
||||||
* @param {Function} specDefinitions function that defines several specs.
|
|
||||||
*/
|
|
||||||
var xdescribe = function(description, specDefinitions) {
|
|
||||||
return jasmine.getEnv().xdescribe(description, specDefinitions);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Provide the XMLHttpRequest class for IE 5.x-6.x:
|
|
||||||
jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
|
|
||||||
try {
|
|
||||||
return new ActiveXObject("Msxml2.XMLHTTP.6.0");
|
|
||||||
} catch(e) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return new ActiveXObject("Msxml2.XMLHTTP.3.0");
|
|
||||||
} catch(e) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return new ActiveXObject("Msxml2.XMLHTTP");
|
|
||||||
} catch(e) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return new ActiveXObject("Microsoft.XMLHTTP");
|
|
||||||
} catch(e) {
|
|
||||||
}
|
|
||||||
throw new Error("This browser does not support XMLHttpRequest.");
|
|
||||||
} : XMLHttpRequest;
|
|
||||||
@@ -1,182 +0,0 @@
|
|||||||
jasmine.TrivialReporter = function(doc) {
|
|
||||||
this.document = doc || document;
|
|
||||||
this.suiteDivs = {};
|
|
||||||
this.logRunningSpecs = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
|
|
||||||
var el = document.createElement(type);
|
|
||||||
|
|
||||||
for (var i = 2; i < arguments.length; i++) {
|
|
||||||
var child = arguments[i];
|
|
||||||
|
|
||||||
if (typeof child === 'string') {
|
|
||||||
el.appendChild(document.createTextNode(child));
|
|
||||||
} else {
|
|
||||||
if (child) { el.appendChild(child); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var attr in attrs) {
|
|
||||||
if (attr == "className") {
|
|
||||||
el[attr] = attrs[attr];
|
|
||||||
} else {
|
|
||||||
el.setAttribute(attr, attrs[attr]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return el;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
|
||||||
var showPassed, showSkipped;
|
|
||||||
|
|
||||||
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
|
|
||||||
this.createDom('div', { className: 'banner' },
|
|
||||||
this.createDom('div', { className: 'logo' },
|
|
||||||
"Jasmine",
|
|
||||||
this.createDom('span', { className: 'version' }, runner.env.versionString())),
|
|
||||||
this.createDom('div', { className: 'options' },
|
|
||||||
"Show ",
|
|
||||||
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
|
|
||||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
|
|
||||||
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
|
|
||||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
|
|
||||||
)
|
|
||||||
),
|
|
||||||
|
|
||||||
this.runnerDiv = this.createDom('div', { className: 'runner running' },
|
|
||||||
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
|
|
||||||
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
|
|
||||||
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
|
|
||||||
);
|
|
||||||
|
|
||||||
this.document.body.appendChild(this.outerDiv);
|
|
||||||
|
|
||||||
var suites = runner.suites();
|
|
||||||
for (var i = 0; i < suites.length; i++) {
|
|
||||||
var suite = suites[i];
|
|
||||||
var suiteDiv = this.createDom('div', { className: 'suite' },
|
|
||||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
|
|
||||||
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
|
|
||||||
this.suiteDivs[suite.id] = suiteDiv;
|
|
||||||
var parentDiv = this.outerDiv;
|
|
||||||
if (suite.parentSuite) {
|
|
||||||
parentDiv = this.suiteDivs[suite.parentSuite.id];
|
|
||||||
}
|
|
||||||
parentDiv.appendChild(suiteDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.startedAt = new Date();
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
showPassed.onchange = function(evt) {
|
|
||||||
if (evt.target.checked) {
|
|
||||||
self.outerDiv.className += ' show-passed';
|
|
||||||
} else {
|
|
||||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
showSkipped.onchange = function(evt) {
|
|
||||||
if (evt.target.checked) {
|
|
||||||
self.outerDiv.className += ' show-skipped';
|
|
||||||
} else {
|
|
||||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
|
|
||||||
var results = runner.results();
|
|
||||||
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
|
|
||||||
this.runnerDiv.setAttribute("class", className);
|
|
||||||
//do it twice for IE
|
|
||||||
this.runnerDiv.setAttribute("className", className);
|
|
||||||
var specs = runner.specs();
|
|
||||||
var specCount = 0;
|
|
||||||
for (var i = 0; i < specs.length; i++) {
|
|
||||||
if (this.specFilter(specs[i])) {
|
|
||||||
specCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
|
|
||||||
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
|
|
||||||
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
|
|
||||||
|
|
||||||
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
|
|
||||||
var results = suite.results();
|
|
||||||
var status = results.passed() ? 'passed' : 'failed';
|
|
||||||
if (results.totalCount == 0) { // todo: change this to check results.skipped
|
|
||||||
status = 'skipped';
|
|
||||||
}
|
|
||||||
this.suiteDivs[suite.id].className += " " + status;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
|
|
||||||
if (this.logRunningSpecs) {
|
|
||||||
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
|
|
||||||
var results = spec.results();
|
|
||||||
var status = results.passed() ? 'passed' : 'failed';
|
|
||||||
if (results.skipped) {
|
|
||||||
status = 'skipped';
|
|
||||||
}
|
|
||||||
var specDiv = this.createDom('div', { className: 'spec ' + status },
|
|
||||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
|
|
||||||
this.createDom('a', {
|
|
||||||
className: 'description',
|
|
||||||
href: '?spec=' + encodeURIComponent(spec.getFullName()),
|
|
||||||
title: spec.getFullName()
|
|
||||||
}, spec.description));
|
|
||||||
|
|
||||||
|
|
||||||
var resultItems = results.getItems();
|
|
||||||
var messagesDiv = this.createDom('div', { className: 'messages' });
|
|
||||||
for (var i = 0; i < resultItems.length; i++) {
|
|
||||||
var result = resultItems[i];
|
|
||||||
|
|
||||||
if (result.type == 'log') {
|
|
||||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
|
||||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
|
||||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
|
||||||
|
|
||||||
if (result.trace.stack) {
|
|
||||||
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (messagesDiv.childNodes.length > 0) {
|
|
||||||
specDiv.appendChild(messagesDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.suiteDivs[spec.suite.id].appendChild(specDiv);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.log = function() {
|
|
||||||
var console = jasmine.getGlobal().console;
|
|
||||||
if (console && console.log) console.log.apply(console, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.getLocation = function() {
|
|
||||||
return this.document.location;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
|
|
||||||
var paramMap = {};
|
|
||||||
var params = this.getLocation().search.substring(1).split('&');
|
|
||||||
for (var i = 0; i < params.length; i++) {
|
|
||||||
var p = params[i].split('=');
|
|
||||||
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!paramMap["spec"]) return true;
|
|
||||||
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
|
|
||||||
};
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
body {
|
|
||||||
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.jasmine_reporter a:visited, .jasmine_reporter a {
|
|
||||||
color: #303;
|
|
||||||
}
|
|
||||||
|
|
||||||
.jasmine_reporter a:hover, .jasmine_reporter a:active {
|
|
||||||
color: blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
.run_spec {
|
|
||||||
float:right;
|
|
||||||
padding-right: 5px;
|
|
||||||
font-size: .8em;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.jasmine_reporter {
|
|
||||||
margin: 0 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner {
|
|
||||||
color: #303;
|
|
||||||
background-color: #fef;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
float: left;
|
|
||||||
font-size: 1.1em;
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo .version {
|
|
||||||
font-size: .6em;
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.runner.running {
|
|
||||||
background-color: yellow;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.options {
|
|
||||||
text-align: right;
|
|
||||||
font-size: .8em;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.suite {
|
|
||||||
border: 1px outset gray;
|
|
||||||
margin: 5px 0;
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.suite .suite {
|
|
||||||
margin: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.suite.passed {
|
|
||||||
background-color: #dfd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.suite.failed {
|
|
||||||
background-color: #fdd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spec {
|
|
||||||
margin: 5px;
|
|
||||||
padding-left: 1em;
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spec.failed, .spec.passed, .spec.skipped {
|
|
||||||
padding-bottom: 5px;
|
|
||||||
border: 1px solid gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spec.failed {
|
|
||||||
background-color: #fbb;
|
|
||||||
border-color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spec.passed {
|
|
||||||
background-color: #bfb;
|
|
||||||
border-color: green;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spec.skipped {
|
|
||||||
background-color: #bbb;
|
|
||||||
}
|
|
||||||
|
|
||||||
.messages {
|
|
||||||
border-left: 1px dashed gray;
|
|
||||||
padding-left: 1em;
|
|
||||||
padding-right: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.passed {
|
|
||||||
background-color: #cfc;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.failed {
|
|
||||||
background-color: #fbb;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skipped {
|
|
||||||
color: #777;
|
|
||||||
background-color: #eee;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*.resultMessage {*/
|
|
||||||
/*white-space: pre;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
.resultMessage span.result {
|
|
||||||
display: block;
|
|
||||||
line-height: 2em;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.resultMessage .mismatch {
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stackTrace {
|
|
||||||
white-space: pre;
|
|
||||||
font-size: .8em;
|
|
||||||
margin-left: 10px;
|
|
||||||
max-height: 5em;
|
|
||||||
overflow: auto;
|
|
||||||
border: 1px inset red;
|
|
||||||
padding: 1em;
|
|
||||||
background: #eef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.finished-at {
|
|
||||||
padding-left: 1em;
|
|
||||||
font-size: .6em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-passed .passed,
|
|
||||||
.show-skipped .skipped {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#jasmine_content {
|
|
||||||
position:fixed;
|
|
||||||
right: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.runner {
|
|
||||||
border: 1px solid gray;
|
|
||||||
display: block;
|
|
||||||
margin: 5px 0;
|
|
||||||
padding: 2px 0 2px 10px;
|
|
||||||
}
|
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
// Mock setTimeout, clearTimeout
|
|
||||||
// Contributed by Pivotal Computer Systems, www.pivotalsf.com
|
|
||||||
|
|
||||||
jasmine.FakeTimer = function() {
|
|
||||||
this.reset();
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
self.setTimeout = function(funcToCall, millis) {
|
|
||||||
self.timeoutsMade++;
|
|
||||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
|
|
||||||
return self.timeoutsMade;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.setInterval = function(funcToCall, millis) {
|
|
||||||
self.timeoutsMade++;
|
|
||||||
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
|
|
||||||
return self.timeoutsMade;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.clearTimeout = function(timeoutKey) {
|
|
||||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.clearInterval = function(timeoutKey) {
|
|
||||||
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.FakeTimer.prototype.reset = function() {
|
|
||||||
this.timeoutsMade = 0;
|
|
||||||
this.scheduledFunctions = {};
|
|
||||||
this.nowMillis = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.FakeTimer.prototype.tick = function(millis) {
|
|
||||||
var oldMillis = this.nowMillis;
|
|
||||||
var newMillis = oldMillis + millis;
|
|
||||||
this.runFunctionsWithinRange(oldMillis, newMillis);
|
|
||||||
this.nowMillis = newMillis;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
|
|
||||||
var scheduledFunc;
|
|
||||||
var funcsToRun = [];
|
|
||||||
for (var timeoutKey in this.scheduledFunctions) {
|
|
||||||
scheduledFunc = this.scheduledFunctions[timeoutKey];
|
|
||||||
if (scheduledFunc != jasmine.undefined &&
|
|
||||||
scheduledFunc.runAtMillis >= oldMillis &&
|
|
||||||
scheduledFunc.runAtMillis <= nowMillis) {
|
|
||||||
funcsToRun.push(scheduledFunc);
|
|
||||||
this.scheduledFunctions[timeoutKey] = jasmine.undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (funcsToRun.length > 0) {
|
|
||||||
funcsToRun.sort(function(a, b) {
|
|
||||||
return a.runAtMillis - b.runAtMillis;
|
|
||||||
});
|
|
||||||
for (var i = 0; i < funcsToRun.length; ++i) {
|
|
||||||
try {
|
|
||||||
var funcToRun = funcsToRun[i];
|
|
||||||
this.nowMillis = funcToRun.runAtMillis;
|
|
||||||
funcToRun.funcToCall();
|
|
||||||
if (funcToRun.recurring) {
|
|
||||||
this.scheduleFunction(funcToRun.timeoutKey,
|
|
||||||
funcToRun.funcToCall,
|
|
||||||
funcToRun.millis,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.runFunctionsWithinRange(oldMillis, nowMillis);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
|
|
||||||
this.scheduledFunctions[timeoutKey] = {
|
|
||||||
runAtMillis: this.nowMillis + millis,
|
|
||||||
funcToCall: funcToCall,
|
|
||||||
recurring: recurring,
|
|
||||||
timeoutKey: timeoutKey,
|
|
||||||
millis: millis
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @namespace
|
|
||||||
*/
|
|
||||||
jasmine.Clock = {
|
|
||||||
defaultFakeTimer: new jasmine.FakeTimer(),
|
|
||||||
|
|
||||||
reset: function() {
|
|
||||||
jasmine.Clock.assertInstalled();
|
|
||||||
jasmine.Clock.defaultFakeTimer.reset();
|
|
||||||
},
|
|
||||||
|
|
||||||
tick: function(millis) {
|
|
||||||
jasmine.Clock.assertInstalled();
|
|
||||||
jasmine.Clock.defaultFakeTimer.tick(millis);
|
|
||||||
},
|
|
||||||
|
|
||||||
runFunctionsWithinRange: function(oldMillis, nowMillis) {
|
|
||||||
jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
|
|
||||||
},
|
|
||||||
|
|
||||||
scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
|
|
||||||
jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
|
|
||||||
},
|
|
||||||
|
|
||||||
useMock: function() {
|
|
||||||
if (!jasmine.Clock.isInstalled()) {
|
|
||||||
var spec = jasmine.getEnv().currentSpec;
|
|
||||||
spec.after(jasmine.Clock.uninstallMock);
|
|
||||||
|
|
||||||
jasmine.Clock.installMock();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
installMock: function() {
|
|
||||||
jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
|
|
||||||
},
|
|
||||||
|
|
||||||
uninstallMock: function() {
|
|
||||||
jasmine.Clock.assertInstalled();
|
|
||||||
jasmine.Clock.installed = jasmine.Clock.real;
|
|
||||||
},
|
|
||||||
|
|
||||||
real: {
|
|
||||||
setTimeout: jasmine.getGlobal().setTimeout,
|
|
||||||
clearTimeout: jasmine.getGlobal().clearTimeout,
|
|
||||||
setInterval: jasmine.getGlobal().setInterval,
|
|
||||||
clearInterval: jasmine.getGlobal().clearInterval
|
|
||||||
},
|
|
||||||
|
|
||||||
assertInstalled: function() {
|
|
||||||
if (!jasmine.Clock.isInstalled()) {
|
|
||||||
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
isInstalled: function() {
|
|
||||||
return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
|
|
||||||
},
|
|
||||||
|
|
||||||
installed: null
|
|
||||||
};
|
|
||||||
jasmine.Clock.installed = jasmine.Clock.real;
|
|
||||||
|
|
||||||
//else for IE support
|
|
||||||
jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
|
|
||||||
if (jasmine.Clock.installed.setTimeout.apply) {
|
|
||||||
return jasmine.Clock.installed.setTimeout.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return jasmine.Clock.installed.setTimeout(funcToCall, millis);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.getGlobal().setInterval = function(funcToCall, millis) {
|
|
||||||
if (jasmine.Clock.installed.setInterval.apply) {
|
|
||||||
return jasmine.Clock.installed.setInterval.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return jasmine.Clock.installed.setInterval(funcToCall, millis);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.getGlobal().clearTimeout = function(timeoutKey) {
|
|
||||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
|
||||||
return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return jasmine.Clock.installed.clearTimeout(timeoutKey);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.getGlobal().clearInterval = function(timeoutKey) {
|
|
||||||
if (jasmine.Clock.installed.clearTimeout.apply) {
|
|
||||||
return jasmine.Clock.installed.clearInterval.apply(this, arguments);
|
|
||||||
} else {
|
|
||||||
return jasmine.Clock.installed.clearInterval(timeoutKey);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/**
|
|
||||||
* @namespace
|
|
||||||
*/
|
|
||||||
jasmine.util = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Declare that a child class inherit it's prototype from the parent class.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Function} childClass
|
|
||||||
* @param {Function} parentClass
|
|
||||||
*/
|
|
||||||
jasmine.util.inherit = function(childClass, parentClass) {
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
var subclass = function() {
|
|
||||||
};
|
|
||||||
subclass.prototype = parentClass.prototype;
|
|
||||||
childClass.prototype = new subclass;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.util.formatException = function(e) {
|
|
||||||
var lineNumber;
|
|
||||||
if (e.line) {
|
|
||||||
lineNumber = e.line;
|
|
||||||
}
|
|
||||||
else if (e.lineNumber) {
|
|
||||||
lineNumber = e.lineNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
var file;
|
|
||||||
|
|
||||||
if (e.sourceURL) {
|
|
||||||
file = e.sourceURL;
|
|
||||||
}
|
|
||||||
else if (e.fileName) {
|
|
||||||
file = e.fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
|
|
||||||
|
|
||||||
if (file && lineNumber) {
|
|
||||||
message += ' in ' + file + ' (line ' + lineNumber + ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
return message;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.util.htmlEscape = function(str) {
|
|
||||||
if (!str) return str;
|
|
||||||
return str.replace(/&/g, '&')
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>');
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.util.argsToArray = function(args) {
|
|
||||||
var arrayOfArgs = [];
|
|
||||||
for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
|
|
||||||
return arrayOfArgs;
|
|
||||||
};
|
|
||||||
|
|
||||||
jasmine.util.extend = function(destination, source) {
|
|
||||||
for (var property in source) destination[property] = source[property];
|
|
||||||
return destination;
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"major": 0,
|
|
||||||
"minor": 11,
|
|
||||||
"build": 1
|
|
||||||
}
|
|
||||||