diff --git a/KoansRunner.html b/KoansRunner.html
index d9fc146d9..a2f67fc2a 100644
--- a/KoansRunner.html
+++ b/KoansRunner.html
@@ -1,33 +1,29 @@
-
+
-
- Javascript Koans
-
-
-
-
-
-
+
+ Javascript Koans
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LICENSE b/LICENSE
index 199f991af..88c6178e7 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2010-2014 David Laing and Greg Malcolm
+Copyright (c) 2010-2020 David Laing, Greg Malcolm, Yan Fan, and Alexander Ogilvie
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
diff --git a/README.markdown b/README.markdown
index 862520fc1..67ac33cf0 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1,13 +1,15 @@
# javascript-koans-esl
-This is [mrdavidlaing's JavaScript Koans](https://github.com/mrdavidlaing/javascript-koans), but with simple English. The vague Buddhist language in the original has been replaced with simple English. Set-up instructions are also added for complete beginners.
-Javascript koans is to teach you JavaScript programming through testing. When you first run the koans, you will be given a 'runtime error' and a 'stack trace' indicating where the error occured.
+This is [mrdavidlaing's JavaScript Koans](https://github.com/mrdavidlaing/javascript-koans), but with simple English, and refactored to use a more modern version of JavaScript. The vague Buddhist language in the original has been replaced with simple English. Setup instructions are also added for complete beginners.
+
+Javascript koans are to teach you JavaScript programming through testing. When you first run the koans, you will be given a 'runtime error' and a 'stack trace' indicating where the error occurred.
Your goal is to find and fix the error.
Through exploring the code and fixing the errors, you will learn new things about the JavaScript language and functional programming.
-#### What are koans?
+## Koans
+
> A koan is a riddle or puzzle that Zen Buddhists use during meditation to help them unravel greater truths about the world and about themselves.
[source](http://www.huffingtonpost.com/entry/zen-buddhism-koan_us_563251dce4b0631799115f3c)
@@ -15,26 +17,29 @@ Through exploring the code and fixing the errors, you will learn new things abou
## Setting Up
### Download Using Git
+
If you know git:
-```code
+```sh
git clone https://github.com/yanarchy/javascript-koans-esl.git
```
### Download Without Git
+
If you do not know git, please download the zip and unzip on your computer.

### Open in Text Editor
-If you do not have a text editor for JavaScript, I highly recommend downloading and installing [Sublime Text](https://www.sublimetext.com/3) or [Atom](https://atom.io/).
-Open this `javascript-koans-esl project` folder in your text editor.
+If you do not have a code editor for JavaScript, we highly recommend downloading and installing [Visual Studio Code](https://code.visualstudio.com/).
+
+Open this `javascript-koans-esl project` folder in your code editor.
## How to Start
-1. Open the `KoansRunner.html` file in the browser (for example, Chrome or Firefox).
+1. Open the `KoansRunner.html` file in your web browser.
2. The first error will be in `koans/AboutExpects.js`.
-
+ 
3. Fix the first test in the `koans/AboutExpects.js` file and save it.
@@ -44,20 +49,20 @@ Open this `javascript-koans-esl project` folder in your text editor.
## Tips
-* Do not think too much about each problem--they are simple, especially in the beginning.
-* Are you really stuck on something? You can disable a test by adding an 'x' to the beginning of 'it(...)'. If you do this, the KoansRunner will skip this particular test and go on to the next. Remember to come back to the tests that you disable!
+- Do not think too much about each problem - they are simple, especially in the beginning.
+- Are you really stuck on something? You can disable a test by adding an `x` to the beginning of `it(...)`. If you do this, the KoansRunner will skip this particular test and go on to the next. Remember to come back to the tests that you disable!
-```code
- xit('should be disabled', function () {
+ ```js
+ xit("should be disabled", function () {
// This is an example
});
-```
+ ```
-* Don't be afraid to Google
-* Don't be afraid to make mistakes
+- Don't be afraid to Google
+- Don't be afraid to make mistakes
## Other Information
Is there anything that needs to be explained in simpler English? Let me know.
-The test runner used is [Jasmine](http://jasmine.github.io/) with a customized report viewer. Understanding Jasmine is not important for finishing this.
\ No newline at end of file
+The test runner used is [Jasmine](http://jasmine.github.io/) with a customized report viewer. Understanding Jasmine is not important for completing these.
diff --git a/koans/AboutApplyingWhatWeHaveLearnt.js b/koans/AboutApplyingWhatWeHaveLearnt.js
index 088e0af17..5283759ba 100644
--- a/koans/AboutApplyingWhatWeHaveLearnt.js
+++ b/koans/AboutApplyingWhatWeHaveLearnt.js
@@ -1,112 +1,112 @@
-var _; //globals
-
-describe("About Applying What We Have Learnt", function() {
-
- var products;
-
- beforeEach(function () {
- products = [
- { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
- { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
- { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
- { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
- { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
- ];
- });
+describe("About Applying What We Have Learnt", () => {
+ const products = [
+ {
+ name: "Sonoma",
+ ingredients: ["artichoke", "sundried tomatoes", "mushrooms"],
+ containsNuts: false,
+ },
+ {
+ name: "Pizza Primavera",
+ ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"],
+ containsNuts: false,
+ },
+ {
+ name: "South Of The Border",
+ ingredients: ["black beans", "jalapenos", "mushrooms"],
+ containsNuts: false,
+ },
+ {
+ name: "Blue Moon",
+ ingredients: ["blue cheese", "garlic", "walnuts"],
+ containsNuts: true,
+ },
+ {
+ name: "Taste Of Athens",
+ ingredients: ["spinach", "kalamata olives", "sesame seeds"],
+ containsNuts: true,
+ },
+ ];
/*********************************************************************************/
- it("should find a pizza I can eat (imperative) because I am allergic to nuts and hate mushrooms", function () {
-
- var i, j, hasMushrooms, productsICanEat = [];
+ it("should find a pizza I can eat (imperative) because I am allergic to nuts and hate mushrooms", () => {
+ let productsICanEat = [];
- for (i = 0; i < products.length; i+=1) {
- if (products[i].containsNuts === false) {
- hasMushrooms = false;
- for (j = 0; j < products[i].ingredients.length; j+=1) {
- if (products[i].ingredients[j] === "mushrooms") {
- hasMushrooms = true;
- }
- }
- if (!hasMushrooms) productsICanEat.push(products[i]);
+ for (const product of products) {
+ if (product.containsNuts === false) {
+ let hasMushrooms = false;
+ for (const ingredient of product.ingredients) {
+ if (ingredient === "mushrooms") {
+ hasMushrooms = true;
+ }
}
+ if (!hasMushrooms) productsICanEat.push(product);
+ }
}
expect(productsICanEat.length).toBe(FILL_ME_IN);
});
- it("should find a pizza I can eat (functional) because I'm allergic to nuts and hate mushrooms", function () {
-
- var productsICanEat = [];
+ it("should find a pizza I can eat (functional) because I'm allergic to nuts and hate mushrooms", () => {
+ var productsICanEat = [];
- /* solve using filter() & all() / any() */
+ /* solve using filter(), every()/some() */
- expect(productsICanEat.length).toBe(FILL_ME_IN);
+ expect(productsICanEat.length).toBe(FILL_ME_IN);
});
/*********************************************************************************/
- it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (imperative)", function () {
-
- var sum = 0;
- for(var i=1; i<1000; i+=1) {
- if (i % 3 === 0 || i % 5 === 0) {
- sum += i;
+ it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (imperative)", () => {
+ let sum = 0;
+ for (let n = 1; n < 1000; n += 1) {
+ if (n % 3 === 0 || n % 5 === 0) {
+ sum += n;
}
}
expect(sum).toBe(FILL_ME_IN);
});
- it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (functional)", function () {
+ it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (functional)", () => {
+ var sum = FILL_ME_IN; /* try chaining Array(length), map(), and reduce() */
- var sum = FILL_ME_IN; /* try chaining range() and reduce() */
-
- expect(233168).toBe(FILL_ME_IN);
+ expect(sum).toBe(233168);
});
/*********************************************************************************/
- it("should count the ingredient occurrence (imperative)", function () {
+ it("should count the ingredient occurrence", () => {
var ingredientCount = { "{ingredient name}": 0 };
- for (i = 0; i < products.length; i+=1) {
- for (j = 0; j < products[i].ingredients.length; j+=1) {
- ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1;
- }
+ for (const product of products) {
+ for (const ingredient of product.ingredients) {
+ ingredientCount[ingredient] = (ingredientCount[ingredient] || 0) + 1;
+ }
}
- expect(ingredientCount['mushrooms']).toBe(FILL_ME_IN);
- });
-
- it("should count the ingredient occurrence (functional)", function () {
- var ingredientCount = { "{ingredient name}": 0 };
-
- /* chain() together map(), flatten() and reduce() */
-
- expect(ingredientCount['mushrooms']).toBe(FILL_ME_IN);
+ expect(ingredientCount["mushrooms"]).toBe(FILL_ME_IN);
});
/*********************************************************************************/
/* UNCOMMENT FOR EXTRA CREDIT */
/*
- it("should find the largest prime factor of a composite number", function () {
+ it("should find the largest prime factor of a composite number", () => {
});
- it("should find the largest palindrome made from the product of two 3 digit numbers", function () {
+ it("should find the largest palindrome made from the product of two 3 digit numbers", () => {
});
- it("should find the smallest number divisible by each of the numbers 1 to 20", function () {
-
+ it("should find the smallest number divisible by each of the numbers 1 to 20", () => {
});
- it("should find the difference between the sum of the squares and the square of the sums", function () {
+ it("should find the difference between the sum of the squares and the square of the sums", () => {
});
- it("should find the 10001st prime", function () {
+ it("should find the 10001st prime", () => {
});
*/
diff --git a/koans/AboutArrays.js b/koans/AboutArrays.js
index 3f7f48d2d..b7f037028 100644
--- a/koans/AboutArrays.js
+++ b/koans/AboutArrays.js
@@ -1,16 +1,23 @@
-describe("About Arrays", function() {
-
- it("should create arrays", function() {
- var emptyArray = [];
+describe("About Arrays", () => {
+ it("should create arrays", () => {
+ const emptyArray = [];
// Learn about data types in JavaScript
- expect(typeof(emptyArray)).toBe(FILL_ME_IN); //A mistake? - https://www.w3schools.com/js/js_datatypes.asp
+ expect(typeof emptyArray).toBe(FILL_ME_IN); // A mistake? - https://www.w3schools.com/js/js_datatypes.asp
expect(emptyArray.length).toBe(FILL_ME_IN);
});
- it("should understand how to access elements in arrays", function () {
- var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
+ it("should understand how to access elements in arrays", () => {
+ const multiTypeArray = [
+ 0,
+ 1,
+ "two",
+ () => 3,
+ { value1: 4, value2: 5 },
+ [6, 7],
+ ];
expect(multiTypeArray[0]).toBe(FILL_ME_IN);
+ expect(multiTypeArray[1]).toBe(FILL_ME_IN);
expect(multiTypeArray[2]).toBe(FILL_ME_IN);
expect(multiTypeArray[3]()).toBe(FILL_ME_IN);
expect(multiTypeArray[4].value1).toBe(FILL_ME_IN);
@@ -18,7 +25,6 @@ describe("About Arrays", function() {
expect(multiTypeArray[5][0]).toBe(FILL_ME_IN);
});
-
/*
An array literal is a list of zero or more expressions. Each expression represents an element in the array.
An array is enclosed in square brackets ([]).
@@ -27,10 +33,9 @@ describe("About Arrays", function() {
elements, and its length is set to the number of arguments specified.
*/
- it("should understand array literals", function () {
-
+ it("should understand array literals", () => {
// The below line is an array literal
- var array = [];
+ const array = [];
expect(array).toEqual([]);
array[0] = 1;
@@ -43,22 +48,22 @@ describe("About Arrays", function() {
expect(array).toEqual(FILL_ME_IN);
});
- it("should understand array length", function () {
- var fourNumberArray = [1, 2, 3, 4];
+ it("should understand array length", () => {
+ const fourNumberArray = [1, 2, 3, 4];
expect(fourNumberArray.length).toBe(FILL_ME_IN);
fourNumberArray.push(5, 6);
expect(fourNumberArray.length).toBe(FILL_ME_IN);
- var tenEmptyElementArray = new Array(10);
+ const tenEmptyElementArray = new Array(10);
expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);
tenEmptyElementArray.length = 5;
expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);
});
- it("should slice arrays", function () {
- var array = ["peanut", "butter", "and", "jelly"];
+ it("should slice arrays", () => {
+ const array = ["peanut", "butter", "and", "jelly"];
expect(array.slice(0, 1)).toEqual(FILL_ME_IN);
expect(array.slice(0, 2)).toEqual(FILL_ME_IN);
@@ -69,42 +74,42 @@ describe("About Arrays", function() {
expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
});
- it("should know array references", function () {
- var array = [ "zero", "one", "two", "three", "four", "five" ];
+ it("should know array references", () => {
+ const array = ["zero", "one", "two", "three", "four", "five"];
function passedByReference(refArray) {
- refArray[1] = "changed in function";
+ refArray[1] = "changed in function";
}
passedByReference(array);
expect(array[1]).toBe(FILL_ME_IN);
- var assignedArray = array;
+ const assignedArray = array;
assignedArray[5] = "changed in assignedArray";
expect(array[5]).toBe(FILL_ME_IN);
- var copyOfArray = array.slice();
+ const copyOfArray = array.slice();
copyOfArray[3] = "changed in copyOfArray";
expect(array[3]).toBe(FILL_ME_IN);
});
- it("should push and pop", function () {
- var array = [1, 2];
+ it("should push and pop", () => {
+ const array = [1, 2];
array.push(3);
expect(array).toEqual(FILL_ME_IN);
- var poppedValue = array.pop();
+ const poppedValue = array.pop();
expect(poppedValue).toBe(FILL_ME_IN);
expect(array).toEqual(FILL_ME_IN);
});
- it("should know about shifting arrays", function () {
- var array = [1, 2];
+ it("should know about shifting arrays", () => {
+ const array = [1, 2];
array.unshift(3);
expect(array).toEqual(FILL_ME_IN);
- var shiftedValue = array.shift();
+ const shiftedValue = array.shift();
expect(shiftedValue).toEqual(FILL_ME_IN);
expect(array).toEqual(FILL_ME_IN);
});
diff --git a/koans/AboutExpects.js b/koans/AboutExpects.js
index 0e783df59..11c3c7981 100644
--- a/koans/AboutExpects.js
+++ b/koans/AboutExpects.js
@@ -1,18 +1,16 @@
-describe('About Expects', function() {
-
+describe("About Expects", () => {
// These are tests. In programming, we also call them 'specs'.
// Specs are expectations of what is true.
- it('should expect true', function() {
-
- // Your journey begins here: Replace the word false with true
+ it("should expect true", () => {
+ // Your journey begins here: Replace the word false with true
expect(false).toBeTruthy();
});
// Is the actual value what we expect? Replace FILL_ME_IN with the value
// that we expect.
- it('should expect equality', function() {
- var expectedValue = FILL_ME_IN;
- var actualValue = 1 + 1;
+ it("should expect equality", () => {
+ const expectedValue = FILL_ME_IN;
+ const actualValue = 1 + 1;
// What do you think === does?
expect(actualValue === expectedValue).toBeTruthy();
@@ -20,28 +18,28 @@ describe('About Expects', function() {
// Some ways of testing truth are better than others. What is different
// about the below test versus the above test?
- it('should assert equality a better way', function() {
- var expectedValue = FILL_ME_IN;
- var actualValue = 1 + 1;
+ it("should assert equality a better way", () => {
+ const expectedValue = FILL_ME_IN;
+ const actualValue = 1 + 1;
- // toEqual() uses regular equality to compare two values. Does 2 equal 1 + 1?
+ // toEqual() uses regular equality to compare two values. Does 2 equal 1 + 1?
expect(actualValue).toEqual(expectedValue);
});
// Sometimes you need to be precise about what you "type."
- it('should assert equality with ===', function() {
- var expectedValue = FILL_ME_IN;
+ it("should assert equality with ===", () => {
+ const expectedValue = FILL_ME_IN;
// A string can be any text or characters inside double or single quotes.
// What do you think toString() does?
- var actualValue = (1 + 1).toString();
+ const actualValue = (1 + 1).toString();
- // toBe() will always use === to compare.
+ // toBe() will always use === to compare.
expect(actualValue).toBe(expectedValue);
});
// You can also simply write in the values.
- it('should have filled in values', function() {
+ it("should have filled in values", () => {
expect(1 + 1).toEqual(FILL_ME_IN);
});
});
diff --git a/koans/AboutFunctions.js b/koans/AboutFunctions.js
index 3a879e6cb..101de37af 100644
--- a/koans/AboutFunctions.js
+++ b/koans/AboutFunctions.js
@@ -1,7 +1,5 @@
-describe("About Functions", function() {
-
- it("should declare functions", function() {
-
+describe("About Functions", () => {
+ it("should declare functions", () => {
function add(a, b) {
return a + b;
}
@@ -9,16 +7,15 @@ describe("About Functions", function() {
expect(add(1, 2)).toBe(FILL_ME_IN);
});
- it("should know inner variables override outer variables", function () {
-
- var message = "Outer";
+ it("should know inner variables override outer variables", () => {
+ const message = "Outer";
function getMessage() {
return message;
}
function overrideMessage() {
- var message = "Inner";
+ const message = "Inner";
return message;
}
@@ -28,10 +25,10 @@ describe("About Functions", function() {
});
// JavaScript has a rule called 'lexical scoping'. Let's learn about it.
- it("should have lexical scoping", function () {
- var variable = "top-level";
+ it("should have lexical scoping", () => {
+ const variable = "top-level";
function parentfunction() {
- var variable = "local";
+ const variable = "local";
function childfunction() {
return variable;
}
@@ -40,23 +37,20 @@ describe("About Functions", function() {
expect(parentfunction()).toBe(FILL_ME_IN);
});
- it("should use lexical scoping to create new functions", function () {
-
+ it("should use lexical scoping to create new functions", () => {
function makeMysteryFunction(makerValue) {
- var newFunction = function doMysteriousThing(param) {
+ return function doMysteriousThing(param) {
return makerValue + param;
};
- return newFunction;
}
- var mysteryFunction3 = makeMysteryFunction(3);
- var mysteryFunction5 = makeMysteryFunction(5);
+ const mysteryFunction3 = makeMysteryFunction(3);
+ const mysteryFunction5 = makeMysteryFunction(5);
expect(mysteryFunction3(10) + mysteryFunction5(5)).toBe(FILL_ME_IN);
});
- it("should allow for more than one function argument", function () {
-
+ it("should allow for more than one function argument", () => {
// You can write functions to take in more than one argument (aka parameter).
function returnFirstArg(firstArg) {
return firstArg;
@@ -70,32 +64,22 @@ describe("About Functions", function() {
expect(returnSecondArg("only give first arg")).toBe(FILL_ME_IN);
- function returnAllArgs() {
- var argsArray = [];
- for (var i = 0; i < arguments.length; i += 1) {
- argsArray.push(arguments[i]);
- }
+ function returnAllArgs(...argsArray) {
return argsArray.join(",");
}
expect(returnAllArgs("first", "second", "third")).toBe(FILL_ME_IN);
});
- it("should pass functions as values", function () {
+ it("should pass functions as values", () => {
+ const appendRules = (name) => `${name} rules!`;
- var appendRules = function (name) {
- return name + " rules!";
- };
+ const appendDoubleRules = (name) => `${name} totally rules!`;
- var appendDoubleRules = function (name) {
- return name + " totally rules!";
- };
-
- var praiseSinger = { givePraise: appendRules };
+ const praiseSinger = { givePraise: appendRules };
expect(praiseSinger.givePraise("John")).toBe(FILL_ME_IN);
praiseSinger.givePraise = appendDoubleRules;
expect(praiseSinger.givePraise("Mary")).toBe(FILL_ME_IN);
-
});
});
diff --git a/koans/AboutHigherOrderFunctions.js b/koans/AboutHigherOrderFunctions.js
index 07c416792..d1ceb53ee 100644
--- a/koans/AboutHigherOrderFunctions.js
+++ b/koans/AboutHigherOrderFunctions.js
@@ -1,90 +1,77 @@
-var _; //globals
-
-/* This section uses a functional extension known as Underscore.js - http://documentcloud.github.com/underscore/
- "Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support
- that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.
- It's the tie to go along with jQuery's tux."
- */
-describe("About Higher Order Functions", function () {
-
- it("should use filter to return array items that meet a criteria", function () {
- var numbers = [1,2,3];
- var odd = _(numbers).filter(function (x) { return x % 2 !== 0 });
+describe("About Higher Order Functions", () => {
+ it("should use 'filter' to return array items that meet a criteria", () => {
+ const numbers = [1, 2, 3];
+ const odd = numbers.filter((x) => x % 2 !== 0);
expect(odd).toEqual(FILL_ME_IN);
expect(odd.length).toBe(FILL_ME_IN);
expect(numbers.length).toBe(FILL_ME_IN);
});
- it("should use 'map' to transform each element", function () {
- var numbers = [1, 2, 3];
- var numbersPlus1 = _(numbers).map(function(x) { return x + 1 });
+ it("should use 'map' to transform each element", () => {
+ const numbers = [1, 2, 3];
+ const numbersPlus1 = numbers.map((x) => x + 1);
expect(numbersPlus1).toEqual(FILL_ME_IN);
expect(numbers).toEqual(FILL_ME_IN);
});
- it("should use 'reduce' to update the same result on each iteration", function () {
- var numbers = [1, 2, 3];
- var reduction = _(numbers).reduce(
- function(/* result from last call */ memo, /* current */ x) { return memo + x }, /* initial */ 0);
+ it("should use 'reduce' to update the same result on each iteration", () => {
+ const numbers = [1, 2, 3];
+ const reduction = numbers.reduce(
+ (/* result from last call */ memo, /* current */ x) => memo + x,
+ /* initial */ 0
+ );
expect(reduction).toBe(FILL_ME_IN);
expect(numbers).toEqual(FILL_ME_IN);
});
- it("should use 'forEach' for simple iteration", function () {
- var numbers = [1,2,3];
- var msg = "";
- var isEven = function (item) {
- msg += (item % 2) === 0;
- };
+ const isEven = (x) => x % 2 === 0;
+
+ it("should use 'forEach' for simple iteration", () => {
+ const numbers = [1, 2, 3];
+ let msg = "";
- _(numbers).forEach(isEven);
+ numbers.forEach((n) => {
+ msg += isEven(n);
+ });
expect(msg).toEqual(FILL_ME_IN);
expect(numbers).toEqual(FILL_ME_IN);
});
- it("should use 'all' to test whether all items pass condition", function () {
- var onlyEven = [2,4,6];
- var mixedBag = [2,4,5,6];
+ it("should use 'every' to test whether all items pass condition", () => {
+ const onlyEven = [2, 4, 6];
+ const mixedBag = [2, 4, 5, 6];
- var isEven = function(x) { return x % 2 === 0 };
-
- expect(_(onlyEven).all(isEven)).toBe(FILL_ME_IN);
- expect(_(mixedBag).all(isEven)).toBe(FILL_ME_IN);
+ expect(onlyEven.every(isEven)).toBe(FILL_ME_IN);
+ expect(mixedBag.every(isEven)).toBe(FILL_ME_IN);
});
- it("should use 'any' to test if any items passes condition" , function () {
- var onlyEven = [2,4,6];
- var mixedBag = [2,4,5,6];
-
- var isEven = function(x) { return x % 2 === 0 };
+ it("should use 'some' to test if any items passes condition", () => {
+ const onlyEven = [2, 4, 6];
+ const mixedBag = [2, 4, 5, 6];
- expect(_(onlyEven).any(isEven)).toBe(FILL_ME_IN);
- expect(_(mixedBag).any(isEven)).toBe(FILL_ME_IN);
+ expect(onlyEven.some(isEven)).toBe(FILL_ME_IN);
+ expect(mixedBag.some(isEven)).toBe(FILL_ME_IN);
});
- it("should use range to generate an array", function() {
- expect(_.range(3)).toEqual(FILL_ME_IN);
- expect(_.range(1, 4)).toEqual(FILL_ME_IN);
- expect(_.range(0, -4, -1)).toEqual(FILL_ME_IN);
+ it("should use 'flat' to make nested arrays easy to work with", () => {
+ expect(
+ [
+ [1, 2],
+ [3, 4],
+ ].flat()
+ ).toEqual(FILL_ME_IN);
});
- it("should use flatten to make nested arrays easy to work with", function() {
- expect(_([ [1, 2], [3, 4] ]).flatten()).toEqual(FILL_ME_IN);
- });
-
- it("should use chain() ... .value() to use multiple higher order functions", function() {
- var result = _([ [0, 1], 2 ]).chain()
- .flatten()
- .map(function(x) { return x+1 } )
- .reduce(function (sum, x) { return sum + x })
- .value();
+ it("should use multiple higher order functions", function () {
+ const result = [[1, 2], 3]
+ .flatMap((x) => x + 1)
+ .filter(isEven)
+ .reduce((sum, x) => sum + x);
- expect(result).toEqual(FILL_ME_IN);
+ expect(result).toEqual(FILL_ME_IN);
});
-
});
-
diff --git a/koans/AboutInheritance.js b/koans/AboutInheritance.js
index c5ab4baf3..422bb31b2 100644
--- a/koans/AboutInheritance.js
+++ b/koans/AboutInheritance.js
@@ -1,85 +1,41 @@
-function Muppet(age, hobby) {
- this.age = age;
- this.hobby = hobby;
-
- this.answerNanny = function() {
- return "Everything's cool!";
+class Muppet {
+ constructor(age, hobby) {
+ this.age = age;
+ this.hobby = hobby;
}
-}
-
-function SwedishChef(age, hobby, mood) {
- Muppet.call(this, age, hobby);
- this.mood = mood;
- this.cook = function() {
- return "Mmmm soup!";
+ answerNanny() {
+ return "Everything's cool!";
}
}
-SwedishChef.prototype = new Muppet();
-
-describe("About inheritance", function() {
- beforeEach(function() {
- this.muppet = new Muppet(2, "coding");
- this.swedishChef = new SwedishChef(2, "cooking", "chillin");
- });
-
- it("should be able to call a method on the derived object", function() {
- expect(this.swedishChef.cook()).toEqual(FILL_ME_IN);
- });
-
- it("should be able to call a method on the base object", function() {
- expect(this.swedishChef.answerNanny()).toEqual(FILL_ME_IN);
- });
-
- it("should set constructor parameters on the base object", function() {
- expect(this.swedishChef.age).toEqual(FILL_ME_IN);
- expect(this.swedishChef.hobby).toEqual(FILL_ME_IN);
- });
-
- it("should set constructor parameters on the derived object", function() {
- expect(this.swedishChef.mood).toEqual(FILL_ME_IN);
- });
-});
-
-// http://javascript.crockford.com/prototypal.html
-Object.prototype.beget = function () {
- function F() {}
- F.prototype = this;
- return new F();
-}
-
-function Gonzo(age, hobby, trick) {
- Muppet.call(this, age, hobby);
- this.trick = trick;
-
- this.doTrick = function() {
- return this.trick;
+class SwedishChef extends Muppet {
+ constructor(age, hobby, mood) {
+ super(age, hobby);
+ this.mood = mood;
+ }
+ cook() {
+ return "Mmmm soup!";
}
}
-//no longer need to call the Muppet (base type) constructor
-Gonzo.prototype = Muppet.prototype.beget();
-
-describe("About Crockford's inheritance improvement", function() {
- beforeEach(function() {
- this.gonzo = new Gonzo(3, "daredevil performer", "eat a tire");
- });
+describe("About inheritance", () => {
+ const swedishChef = new SwedishChef(2, "cooking", "chillin'");
- it("should be able to call a method on the derived object", function() {
- expect(this.gonzo.doTrick()).toEqual(FILL_ME_IN);
+ it("should be able to call a method on the derived object", () => {
+ expect(swedishChef.cook()).toEqual(FILL_ME_IN);
});
- it("should be able to call a method on the base object", function() {
- expect(this.gonzo.answerNanny()).toEqual(FILL_ME_IN);
+ it("should be able to call a method on the base object", () => {
+ expect(swedishChef.answerNanny()).toEqual(FILL_ME_IN);
});
- it("should set constructor parameters on the base object", function() {
- expect(this.gonzo.age).toEqual(FILL_ME_IN);
- expect(this.gonzo.hobby).toEqual(FILL_ME_IN);
+ it("should set constructor parameters on the base object", () => {
+ expect(swedishChef.age).toEqual(2);
+ expect(swedishChef.hobby).toEqual(FILL_ME_IN);
});
- it("should set constructor parameters on the derived object", function() {
- expect(this.gonzo.trick).toEqual(FILL_ME_IN);
+ it("should set constructor parameters on the derived object", () => {
+ expect(swedishChef.mood).toEqual(FILL_ME_IN);
});
});
diff --git a/koans/AboutMutability.js b/koans/AboutMutability.js
index 28b85cdb6..96c3d9308 100644
--- a/koans/AboutMutability.js
+++ b/koans/AboutMutability.js
@@ -1,63 +1,69 @@
// For beginners, this section jumps deeper into JavaScript and will require a bit more Googling.
-describe("About Mutability", function() {
+describe("About Mutability", () => {
/*
What does 'Mutability' mean? What does it mean for something to be 'mutable'?
Mutable is a type of variable that can be changed. Let's discover what the rules of mutability
are in JavaScript
*/
- it("should expect object properties to be public and mutable", function () {
- var aPerson = { firstname: "John", lastname: "Smith" };
- aPerson.firstname = "Alan";
+ it("should expect object properties to be public and mutable", () => {
+ const aPerson = { firstName: "John", lastName: "Smith" };
+ aPerson.firstName = "Alan";
- expect(aPerson.firstname).toBe(FILL_ME_IN);
+ expect(aPerson.firstName).toBe(FILL_ME_IN);
});
- it("should understand that constructed properties are public and mutable", function () {
- function Person(firstname, lastname) {
- // Waaaahhh! What is this? Try to see if you can fix this error without fully understanding 'this' first.
- this.firstname = firstname;
- this.lastname = lastname;
+ it("should understand that constructed properties are public and mutable", () => {
+ class Person {
+ constructor(firstName, lastName) {
+ // Waaaahhh! What is this? Try to see if you can complete this koan without fully understanding 'this' first.
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
}
- var aPerson = new Person ("John", "Smith");
- aPerson.firstname = "Alan";
+ const aPerson = new Person("John", "Smith");
+ aPerson.firstName = "Alan";
- expect(aPerson.firstname).toBe(FILL_ME_IN);
+ expect(aPerson.firstName).toBe(FILL_ME_IN);
});
// What is a prototype in JavaScript?
- it("should expect prototype properties to be public and mutable", function () {
- function Person(firstname, lastname) {
- this.firstname = firstname;
- this.lastname = lastname;
+ it("should expect prototype properties to be public and mutable", () => {
+ class Person {
+ constructor(firstName, lastName) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+
+ getFullName() {
+ return `${this.firstName} ${this.lastName}`;
+ }
}
- Person.prototype.getFullName = function () {
- return this.firstname + " " + this.lastname;
- };
- var aPerson = new Person ("John", "Smith");
+ const aPerson = new Person("John", "Smith");
expect(aPerson.getFullName()).toBe(FILL_ME_IN);
aPerson.getFullName = function () {
- return this.lastname + ", " + this.firstname;
+ return `${this.lastName}, ${this.firstName}`;
};
expect(aPerson.getFullName()).toBe(FILL_ME_IN);
});
// What is a constructor? What do you think it does?
- it("should know that variables inside a constructor and constructor arguments are private", function () {
- function Person(firstname, lastname) {
- var fullName = firstname + " " + lastname;
-
- this.getFirstName = function () { return firstname; };
- this.getLastName = function () { return lastname; };
- this.getFullName = function () { return fullName; };
+ it("should know that variables inside a constructor and constructor arguments are private", () => {
+ class Person {
+ constructor(firstName, lastName) {
+ const fullName = `${firstName} ${lastName}`;
+ this.getFirstName = () => firstName;
+ this.getLastName = () => lastName;
+ this.getFullName = () => fullName;
+ }
}
- var aPerson = new Person ("John", "Smith");
+ const aPerson = new Person("John", "Smith");
- aPerson.firstname = "Penny";
- aPerson.lastname = "Andrews";
+ aPerson.firstName = "Penny";
+ aPerson.lastName = "Andrews";
aPerson.fullName = "Penny Andrews";
expect(aPerson.getFirstName()).toBe(FILL_ME_IN);
@@ -65,10 +71,9 @@ describe("About Mutability", function() {
expect(aPerson.getFullName()).toBe(FILL_ME_IN);
aPerson.getFullName = function () {
- return aPerson.lastname + ", " + aPerson.firstname;
+ return `${aPerson.lastName}, ${aPerson.firstName}`;
};
expect(aPerson.getFullName()).toBe(FILL_ME_IN);
});
-
});
diff --git a/koans/AboutObjects.js b/koans/AboutObjects.js
index 164f2360f..536a8ccdc 100644
--- a/koans/AboutObjects.js
+++ b/koans/AboutObjects.js
@@ -1,81 +1,70 @@
-describe("About Objects", function () {
+describe("About Objects", () => {
+ describe("Properties", () => {
+ const villains = { mastermind: "Joker", henchwoman: "Harley" };
- describe("Properties", function () {
- var villains;
-
- beforeEach(function () {
- villains = { mastermind: "Joker", henchwoman: "Harley" };
- });
-
- it("should confirm that objects are collections of properties", function () {
+ it("should confirm that objects are collections of properties", () => {
expect(villains.mastermind).toBe(FILL_ME_IN);
});
- it("should confirm that properties are case sensitive", function () {
+ it("should confirm that properties are case sensitive", () => {
expect(villains.henchwoman).toBe(FILL_ME_IN);
expect(villains.henchWoman).toBe(FILL_ME_IN);
});
});
-
- it("should know that functions in objects are called methods", function () {
- var megalomaniac = {
- mastermind : "Brain",
+ it("should know that functions in objects are called methods", () => {
+ const megalomaniac = {
+ mastermind: "Brain",
henchman: "Pinky",
- battleCry: function (noOfBrains) {
- return "They are " + this.henchman + " and the" +
- Array(noOfBrains + 1).join(" " + this.mastermind);
- }
+ battleCry(noOfBrains) {
+ return `They're ${this.henchman} and the ${Array(noOfBrains)
+ .fill(this.mastermind)
+ .join(" ")}`;
+ },
};
- var battleCry = megalomaniac.battleCry(4);
- expect(FILL_ME_IN).toMatch(battleCry);
+ const battleCry = megalomaniac.battleCry(4);
+ expect(battleCry).toMatch(FILL_ME_IN);
});
- it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
- var currentDate = new Date();
- var currentYear = (currentDate.getFullYear());
- var megalomaniac = {
+ it("should confirm that when a function is attached to an object, 'this' refers to the object", () => {
+ const currentDate = new Date();
+ const currentYear = currentDate.getFullYear();
+ const megalomaniac = {
mastermind: "James Wood",
henchman: "Adam West",
birthYear: 1970,
- calculateAge: function () {
+ calculateAge() {
return currentYear - this.birthYear;
- }
+ },
};
expect(currentYear).toBe(FILL_ME_IN);
expect(megalomaniac.calculateAge()).toBe(FILL_ME_IN);
});
- describe("'in' keyword", function () {
- var megalomaniac;
- beforeEach(function () {
- megalomaniac = {
- mastermind: "The Monarch",
- henchwoman: "Dr. Girlfriend",
- theBomb: true
- };
- });
-
- it("should have the bomb", function () {
+ describe("'in' keyword", () => {
+ const megalomaniac = {
+ mastermind: "The Monarch",
+ henchwoman: "Dr. Girlfriend",
+ theBomb: true,
+ };
- var hasBomb = "theBomb" in megalomaniac;
+ it("should have the bomb", () => {
+ const hasBomb = "theBomb" in megalomaniac;
expect(hasBomb).toBe(FILL_ME_IN);
});
- it("should not have the detonator however", function () {
-
- var hasDetonator = "theDetonator" in megalomaniac;
+ it("should not have the detonator however", () => {
+ const hasDetonator = "theDetonator" in megalomaniac;
expect(hasDetonator).toBe(FILL_ME_IN);
});
});
- it("should know that properties can be added and deleted", function () {
- var megalomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };
-
+ it("should know that properties can be added and deleted", () => {
+ const megalomaniac = { mastermind: "Agent Smith", henchman: "Agent Smith" };
expect("secretary" in megalomaniac).toBe(FILL_ME_IN);
megalomaniac.secretary = "Agent Smith";
@@ -85,24 +74,25 @@ describe("About Objects", function () {
expect("henchman" in megalomaniac).toBe(FILL_ME_IN);
});
-
- it("should use prototype to add to all objects", function () {
- function Circle(radius) {
+ it("should use prototype to add to all objects", () => {
+ class Circle {
+ constructor(radius) {
this.radius = radius;
}
+ }
- var simpleCircle = new Circle(10);
- var colouredCircle = new Circle(5);
- colouredCircle.colour = "red";
+ const simpleCircle = new Circle(10);
+ const colouredCircle = new Circle(5);
+ colouredCircle.colour = "red";
- expect(simpleCircle.colour).toBe(FILL_ME_IN);
- expect(colouredCircle.colour).toBe(FILL_ME_IN);
+ expect(simpleCircle.colour).toBe(FILL_ME_IN);
+ expect(colouredCircle.colour).toBe(FILL_ME_IN);
- Circle.prototype.describe = function () {
- return "This circle has a radius of: " + this.radius;
- };
+ Circle.prototype.describe = function () {
+ return `This circle has a radius of: ${this.radius}`;
+ };
- expect(simpleCircle.describe()).toBe(FILL_ME_IN);
- expect(colouredCircle.describe()).toBe(FILL_ME_IN);
+ expect(simpleCircle.describe()).toBe(FILL_ME_IN);
+ expect(colouredCircle.describe()).toBe(FILL_ME_IN);
});
});
diff --git a/lib/FILL_ME_IN.js b/lib/FILL_ME_IN.js
deleted file mode 100644
index 114117d2f..000000000
--- a/lib/FILL_ME_IN.js
+++ /dev/null
@@ -1 +0,0 @@
-var FILL_ME_IN = "Fill this value in";
diff --git a/lib/jasmine/jasmine-html.js b/lib/jasmine/jasmine-html.js
index b4058216c..1d9449f49 100644
--- a/lib/jasmine/jasmine-html.js
+++ b/lib/jasmine/jasmine-html.js
@@ -1,19 +1,644 @@
-jasmine.TrivialReporter = function(doc) {
+jasmine.HtmlReporterHelpers = {};
+
+jasmine.HtmlReporterHelpers.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.HtmlReporterHelpers.getSpecStatus = function (child) {
+ var results = child.results();
+ var status = results.passed() ? "passed" : "failed";
+ if (results.skipped) {
+ status = "skipped";
+ }
+
+ return status;
+};
+
+jasmine.HtmlReporterHelpers.appendToSummary = function (child, childElement) {
+ var parentDiv = this.dom.summary;
+ var parentSuite =
+ typeof child.parentSuite == "undefined" ? "suite" : "parentSuite";
+ var parent = child[parentSuite];
+
+ if (parent) {
+ if (typeof this.views.suites[parent.id] == "undefined") {
+ this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(
+ parent,
+ this.dom,
+ this.views
+ );
+ }
+ parentDiv = this.views.suites[parent.id].element;
+ }
+
+ parentDiv.appendChild(childElement);
+};
+
+jasmine.HtmlReporterHelpers.addHelpers = function (ctor) {
+ for (var fn in jasmine.HtmlReporterHelpers) {
+ ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn];
+ }
+};
+
+jasmine.HtmlReporter = function (_doc) {
+ var self = this;
+ var doc = _doc || window.document;
+
+ var reporterView;
+
+ var dom = {};
+
+ // Jasmine Reporter Public Interface
+ self.logRunningSpecs = false;
+
+ self.reportRunnerStarting = function (runner) {
+ var specs = runner.specs() || [];
+
+ if (specs.length == 0) {
+ return;
+ }
+
+ createReporterDom(runner.env.versionString());
+ doc.body.appendChild(dom.reporter);
+ setExceptionHandling();
+
+ reporterView = new jasmine.HtmlReporter.ReporterView(dom);
+ reporterView.addSpecs(specs, self.specFilter);
+ };
+
+ self.reportRunnerResults = function (runner) {
+ reporterView && reporterView.complete();
+ };
+
+ self.reportSuiteResults = function (suite) {
+ reporterView.suiteComplete(suite);
+ };
+
+ self.reportSpecStarting = function (spec) {
+ if (self.logRunningSpecs) {
+ self.log(
+ ">> Jasmine Running " +
+ spec.suite.description +
+ " " +
+ spec.description +
+ "..."
+ );
+ }
+ };
+
+ self.reportSpecResults = function (spec) {
+ reporterView.specComplete(spec);
+ };
+
+ self.log = function () {
+ var console = jasmine.getGlobal().console;
+ if (console && console.log) {
+ if (console.log.apply) {
+ console.log.apply(console, arguments);
+ } else {
+ console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
+ }
+ }
+ };
+
+ self.specFilter = function (spec) {
+ if (!focusedSpecName()) {
+ return true;
+ }
+
+ return spec.getFullName().indexOf(focusedSpecName()) === 0;
+ };
+
+ return self;
+
+ function focusedSpecName() {
+ var specName;
+
+ (function memoizeFocusedSpec() {
+ if (specName) {
+ return;
+ }
+
+ var paramMap = [];
+ var params = jasmine.HtmlReporter.parameters(doc);
+
+ for (var i = 0; i < params.length; i++) {
+ var p = params[i].split("=");
+ paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
+ }
+
+ specName = paramMap.spec;
+ })();
+
+ return specName;
+ }
+
+ function createReporterDom(version) {
+ dom.reporter = self.createDom(
+ "div",
+ { id: "HTMLReporter", className: "jasmine_reporter" },
+ (dom.banner = self.createDom(
+ "div",
+ { className: "banner" },
+ self.createDom("span", { className: "title" }, "Jasmine "),
+ self.createDom("span", { className: "version" }, version)
+ )),
+
+ (dom.symbolSummary = self.createDom("ul", {
+ className: "symbolSummary",
+ })),
+ (dom.alert = self.createDom(
+ "div",
+ { className: "alert" },
+ self.createDom(
+ "span",
+ { className: "exceptions" },
+ self.createDom(
+ "label",
+ { className: "label", for: "no_try_catch" },
+ "No try/catch"
+ ),
+ self.createDom("input", { id: "no_try_catch", type: "checkbox" })
+ )
+ )),
+ (dom.results = self.createDom(
+ "div",
+ { className: "results" },
+ (dom.summary = self.createDom("div", { className: "summary" })),
+ (dom.details = self.createDom("div", { id: "details" }))
+ ))
+ );
+ }
+
+ function noTryCatch() {
+ return window.location.search.match(/catch=false/);
+ }
+
+ function searchWithCatch() {
+ var params = jasmine.HtmlReporter.parameters(window.document);
+ var removed = false;
+ var i = 0;
+
+ while (!removed && i < params.length) {
+ if (params[i].match(/catch=/)) {
+ params.splice(i, 1);
+ removed = true;
+ }
+ i++;
+ }
+ if (jasmine.CATCH_EXCEPTIONS) {
+ params.push("catch=false");
+ }
+
+ return params.join("&");
+ }
+
+ function setExceptionHandling() {
+ var chxCatch = document.getElementById("no_try_catch");
+
+ if (noTryCatch()) {
+ chxCatch.setAttribute("checked", true);
+ jasmine.CATCH_EXCEPTIONS = false;
+ }
+ chxCatch.onclick = function () {
+ window.location.search = searchWithCatch();
+ };
+ }
+};
+jasmine.HtmlReporter.parameters = function (doc) {
+ var paramStr = doc.location.search.substring(1);
+ var params = [];
+
+ if (paramStr.length > 0) {
+ params = paramStr.split("&");
+ }
+ return params;
+};
+jasmine.HtmlReporter.sectionLink = function (sectionName) {
+ var link = "?";
+ var params = [];
+
+ if (sectionName) {
+ params.push("spec=" + encodeURIComponent(sectionName));
+ }
+ if (!jasmine.CATCH_EXCEPTIONS) {
+ params.push("catch=false");
+ }
+ if (params.length > 0) {
+ link += params.join("&");
+ }
+
+ return link;
+};
+jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);
+jasmine.HtmlReporter.ReporterView = function (dom) {
+ this.startedAt = new Date();
+ this.runningSpecCount = 0;
+ this.completeSpecCount = 0;
+ this.passedCount = 0;
+ this.failedCount = 0;
+ this.skippedCount = 0;
+
+ this.createResultsMenu = function () {
+ this.resultsMenu = this.createDom(
+ "span",
+ { className: "resultsMenu bar" },
+ (this.summaryMenuItem = this.createDom(
+ "a",
+ { className: "summaryMenuItem", href: "#" },
+ "0 specs"
+ )),
+ " | ",
+ (this.detailsMenuItem = this.createDom(
+ "a",
+ { className: "detailsMenuItem", href: "#" },
+ "0 failing"
+ ))
+ );
+
+ this.summaryMenuItem.onclick = function () {
+ dom.reporter.className = dom.reporter.className.replace(
+ / showDetails/g,
+ ""
+ );
+ };
+
+ this.detailsMenuItem.onclick = function () {
+ showDetails();
+ };
+ };
+
+ this.addSpecs = function (specs, specFilter) {
+ this.totalSpecCount = specs.length;
+
+ this.views = {
+ specs: {},
+ suites: {},
+ };
+
+ for (var i = 0; i < specs.length; i++) {
+ var spec = specs[i];
+ this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(
+ spec,
+ dom,
+ this.views
+ );
+ if (specFilter(spec)) {
+ this.runningSpecCount++;
+ }
+ }
+ };
+
+ this.specComplete = function (spec) {
+ this.completeSpecCount++;
+
+ if (isUndefined(this.views.specs[spec.id])) {
+ this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom);
+ }
+
+ var specView = this.views.specs[spec.id];
+
+ switch (specView.status()) {
+ case "passed":
+ this.passedCount++;
+ break;
+
+ case "failed":
+ this.failedCount++;
+ break;
+
+ case "skipped":
+ this.skippedCount++;
+ break;
+ }
+
+ specView.refresh();
+ this.refresh();
+ };
+
+ this.suiteComplete = function (suite) {
+ var suiteView = this.views.suites[suite.id];
+ if (isUndefined(suiteView)) {
+ return;
+ }
+ suiteView.refresh();
+ };
+
+ this.refresh = function () {
+ if (isUndefined(this.resultsMenu)) {
+ this.createResultsMenu();
+ }
+
+ // currently running UI
+ if (isUndefined(this.runningAlert)) {
+ this.runningAlert = this.createDom("a", {
+ href: jasmine.HtmlReporter.sectionLink(),
+ className: "runningAlert bar",
+ });
+ dom.alert.appendChild(this.runningAlert);
+ }
+ this.runningAlert.innerHTML =
+ "Running " +
+ this.completeSpecCount +
+ " of " +
+ specPluralizedFor(this.totalSpecCount);
+
+ // skipped specs UI
+ if (isUndefined(this.skippedAlert)) {
+ this.skippedAlert = this.createDom("a", {
+ href: jasmine.HtmlReporter.sectionLink(),
+ className: "skippedAlert bar",
+ });
+ }
+
+ this.skippedAlert.innerHTML =
+ "Skipping " +
+ this.skippedCount +
+ " of " +
+ specPluralizedFor(this.totalSpecCount) +
+ " - run all";
+
+ if (this.skippedCount === 1 && isDefined(dom.alert)) {
+ dom.alert.appendChild(this.skippedAlert);
+ }
+
+ // passing specs UI
+ if (isUndefined(this.passedAlert)) {
+ this.passedAlert = this.createDom("span", {
+ href: jasmine.HtmlReporter.sectionLink(),
+ className: "passingAlert bar",
+ });
+ }
+ this.passedAlert.innerHTML =
+ "Passing " + specPluralizedFor(this.passedCount);
+
+ // failing specs UI
+ if (isUndefined(this.failedAlert)) {
+ this.failedAlert = this.createDom("span", {
+ href: "?",
+ className: "failingAlert bar",
+ });
+ }
+ this.failedAlert.innerHTML =
+ "Failing " + specPluralizedFor(this.failedCount);
+
+ if (this.failedCount === 1 && isDefined(dom.alert)) {
+ dom.alert.appendChild(this.failedAlert);
+ dom.alert.appendChild(this.resultsMenu);
+ }
+
+ // summary info
+ this.summaryMenuItem.innerHTML =
+ "" + specPluralizedFor(this.runningSpecCount);
+ this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
+ };
+
+ this.complete = function () {
+ dom.alert.removeChild(this.runningAlert);
+
+ this.skippedAlert.innerHTML =
+ "Ran " +
+ this.runningSpecCount +
+ " of " +
+ specPluralizedFor(this.totalSpecCount) +
+ " - run all";
+
+ if (this.failedCount === 0) {
+ dom.alert.appendChild(
+ this.createDom(
+ "span",
+ { className: "passingAlert bar" },
+ "Passing " + specPluralizedFor(this.passedCount)
+ )
+ );
+ } else {
+ showDetails();
+ }
+
+ dom.banner.appendChild(
+ this.createDom(
+ "span",
+ { className: "duration" },
+ "finished in " +
+ (new Date().getTime() - this.startedAt.getTime()) / 1000 +
+ "s"
+ )
+ );
+ };
+
+ return this;
+
+ function showDetails() {
+ if (dom.reporter.className.search(/showDetails/) === -1) {
+ dom.reporter.className += " showDetails";
+ }
+ }
+
+ function isUndefined(obj) {
+ return typeof obj === "undefined";
+ }
+
+ function isDefined(obj) {
+ return !isUndefined(obj);
+ }
+
+ function specPluralizedFor(count) {
+ var str = count + " spec";
+ if (count > 1) {
+ str += "s";
+ }
+ return str;
+ }
+};
+
+jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView);
+
+jasmine.HtmlReporter.SpecView = function (spec, dom, views) {
+ this.spec = spec;
+ this.dom = dom;
+ this.views = views;
+
+ this.symbol = this.createDom("li", { className: "pending" });
+ this.dom.symbolSummary.appendChild(this.symbol);
+
+ this.summary = this.createDom(
+ "div",
+ { className: "specSummary" },
+ this.createDom(
+ "a",
+ {
+ className: "description",
+ href: jasmine.HtmlReporter.sectionLink(this.spec.getFullName()),
+ title: this.spec.getFullName(),
+ },
+ this.spec.description
+ )
+ );
+
+ this.detail = this.createDom(
+ "div",
+ { className: "specDetail" },
+ this.createDom(
+ "a",
+ {
+ className: "description",
+ href: "?spec=" + encodeURIComponent(this.spec.getFullName()),
+ title: this.spec.getFullName(),
+ },
+ this.spec.getFullName()
+ )
+ );
+};
+
+jasmine.HtmlReporter.SpecView.prototype.status = function () {
+ return this.getSpecStatus(this.spec);
+};
+
+jasmine.HtmlReporter.SpecView.prototype.refresh = function () {
+ this.symbol.className = this.status();
+
+ switch (this.status()) {
+ case "skipped":
+ break;
+
+ case "passed":
+ this.appendSummaryToSuiteDiv();
+ break;
+
+ case "failed":
+ this.appendSummaryToSuiteDiv();
+ this.appendFailureDetail();
+ break;
+ }
+};
+
+jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function () {
+ this.summary.className += " " + this.status();
+ this.appendToSummary(this.spec, this.summary);
+};
+
+jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function () {
+ this.detail.className += " " + this.status();
+
+ var resultItems = this.spec.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) {
+ this.detail.appendChild(messagesDiv);
+ this.dom.details.appendChild(this.detail);
+ }
+};
+
+jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);
+jasmine.HtmlReporter.SuiteView = function (suite, dom, views) {
+ this.suite = suite;
+ this.dom = dom;
+ this.views = views;
+
+ this.element = this.createDom(
+ "div",
+ { className: "suite" },
+ this.createDom(
+ "a",
+ {
+ className: "description",
+ href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()),
+ },
+ this.suite.description
+ )
+ );
+
+ this.appendToSummary(this.suite, this.element);
+};
+
+jasmine.HtmlReporter.SuiteView.prototype.status = function () {
+ return this.getSpecStatus(this.suite);
+};
+
+jasmine.HtmlReporter.SuiteView.prototype.refresh = function () {
+ this.element.className += " " + this.status();
+};
+
+jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView);
+
+/* @deprecated Use jasmine.HtmlReporter instead
+ */
+jasmine.TrivialReporter = function (doc) {
this.document = doc || document;
this.suiteDivs = {};
this.logRunningSpecs = false;
};
-jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
+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') {
+ if (typeof child === "string") {
el.appendChild(document.createTextNode(child));
} else {
- if (child) { el.appendChild(child); }
+ if (child) {
+ el.appendChild(child);
+ }
}
}
@@ -28,37 +653,88 @@ jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarA
return el;
};
-jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
+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.outerDiv = this.createDom(
+ "div",
+ { id: "TrivialReporter", className: "jasmine_reporter" },
+ this.createDom(
+ "div",
+ { className: "banner" },
+ this.createDom(
+ "div",
+ { className: "logo" },
+ this.createDom("span", { className: "title" }, "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.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));
+ 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) {
@@ -70,26 +746,32 @@ jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
this.startedAt = new Date();
var self = this;
- showPassed.onchange = function(evt) {
- if (evt.target.checked) {
- self.outerDiv.className += ' show-passed';
+ showPassed.onclick = function (evt) {
+ if (showPassed.checked) {
+ self.outerDiv.className += " show-passed";
} else {
- self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
+ self.outerDiv.className = self.outerDiv.className.replace(
+ / show-passed/,
+ ""
+ );
}
};
- showSkipped.onchange = function(evt) {
- if (evt.target.checked) {
- self.outerDiv.className += ' show-skipped';
+ showSkipped.onclick = function (evt) {
+ if (showSkipped.checked) {
+ self.outerDiv.className += " show-skipped";
} else {
- self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
+ self.outerDiv.className = self.outerDiv.className.replace(
+ / show-skipped/,
+ ""
+ );
}
};
};
-jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
+jasmine.TrivialReporter.prototype.reportRunnerResults = function (runner) {
var results = runner.results();
- var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
+ var className = results.failedCount > 0 ? "runner failed" : "runner passed";
this.runnerDiv.setAttribute("class", className);
//do it twice for IE
this.runnerDiv.setAttribute("className", className);
@@ -100,55 +782,103 @@ jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
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);
+ 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()));
+ this.finishedAtSpan.appendChild(
+ document.createTextNode("Finished at " + new Date().toString())
+ );
};
-jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
+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';
+ 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) {
+jasmine.TrivialReporter.prototype.reportSpecStarting = function (spec) {
if (this.logRunningSpecs) {
- this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
+ this.log(
+ ">> Jasmine Running " +
+ spec.suite.description +
+ " " +
+ spec.description +
+ "..."
+ );
}
};
-jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
+jasmine.TrivialReporter.prototype.reportSpecResults = function (spec) {
var results = spec.results();
- var status = results.passed() ? 'passed' : 'failed';
+ var status = results.passed() ? "passed" : "failed";
if (results.skipped) {
- status = '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 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' });
+ 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.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));
+ messagesDiv.appendChild(
+ this.createDom("div", { className: "stackTrace" }, result.trace.stack)
+ );
}
}
}
@@ -160,23 +890,31 @@ jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
this.suiteDivs[spec.suite.id].appendChild(specDiv);
};
-jasmine.TrivialReporter.prototype.log = function() {
+jasmine.TrivialReporter.prototype.log = function () {
var console = jasmine.getGlobal().console;
- if (console && console.log) console.log.apply(console, arguments);
+ if (console && console.log) {
+ if (console.log.apply) {
+ console.log.apply(console, arguments);
+ } else {
+ console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
+ }
+ }
};
-jasmine.TrivialReporter.prototype.getLocation = function() {
+jasmine.TrivialReporter.prototype.getLocation = function () {
return this.document.location;
};
-jasmine.TrivialReporter.prototype.specFilter = function(spec) {
+jasmine.TrivialReporter.prototype.specFilter = function (spec) {
var paramMap = {};
- var params = this.getLocation().search.substring(1).split('&');
+ var params = this.getLocation().search.substring(1).split("&");
for (var i = 0; i < params.length; i++) {
- var p = params[i].split('=');
+ var p = params[i].split("=");
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
}
- if (!paramMap["spec"]) return true;
- return spec.getFullName().indexOf(paramMap["spec"]) == 0;
+ if (!paramMap.spec) {
+ return true;
+ }
+ return spec.getFullName().indexOf(paramMap.spec) === 0;
};
diff --git a/lib/jasmine/jasmine.css b/lib/jasmine/jasmine.css
index 6583fe7c6..65f750f5d 100644
--- a/lib/jasmine/jasmine.css
+++ b/lib/jasmine/jasmine.css
@@ -1,139 +1,328 @@
body {
- font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
+ background-color: #eeeeee;
+ padding: 0;
+ margin: 5px;
+ overflow-y: scroll;
}
-
-.jasmine_reporter a:visited, .jasmine_reporter a {
- color: #303;
+#HTMLReporter {
+ font-size: 11px;
+ font-family: Monaco, "Lucida Console", monospace;
+ line-height: 14px;
+ color: #333333;
}
-
-.jasmine_reporter a:hover, .jasmine_reporter a:active {
- color: blue;
+#HTMLReporter a {
+ text-decoration: none;
}
-
-.run_spec {
- float:right;
- padding-right: 5px;
- font-size: .8em;
+#HTMLReporter a:hover {
+ text-decoration: underline;
+}
+#HTMLReporter p,
+#HTMLReporter h1,
+#HTMLReporter h2,
+#HTMLReporter h3,
+#HTMLReporter h4,
+#HTMLReporter h5,
+#HTMLReporter h6 {
+ margin: 0;
+ line-height: 14px;
+}
+#HTMLReporter .banner,
+#HTMLReporter .symbolSummary,
+#HTMLReporter .summary,
+#HTMLReporter .resultMessage,
+#HTMLReporter .specDetail .description,
+#HTMLReporter .alert .bar,
+#HTMLReporter .stackTrace {
+ padding-left: 9px;
+ padding-right: 9px;
+}
+#HTMLReporter #jasmine_content {
+ position: fixed;
+ right: 100%;
+}
+#HTMLReporter .version {
+ color: #aaaaaa;
+}
+#HTMLReporter .banner {
+ margin-top: 14px;
+}
+#HTMLReporter .duration {
+ color: #aaaaaa;
+ float: right;
+}
+#HTMLReporter .symbolSummary {
+ overflow: hidden;
+ *zoom: 1;
+ margin: 14px 0;
+}
+#HTMLReporter .symbolSummary li {
+ display: block;
+ float: left;
+ height: 7px;
+ width: 14px;
+ margin-bottom: 7px;
+ font-size: 16px;
+}
+#HTMLReporter .symbolSummary li.passed {
+ font-size: 14px;
+}
+#HTMLReporter .symbolSummary li.passed:before {
+ color: #5e7d00;
+ content: "\02022";
+}
+#HTMLReporter .symbolSummary li.failed {
+ line-height: 9px;
+}
+#HTMLReporter .symbolSummary li.failed:before {
+ color: #b03911;
+ content: "x";
+ font-weight: bold;
+ margin-left: -1px;
+}
+#HTMLReporter .symbolSummary li.skipped {
+ font-size: 14px;
+}
+#HTMLReporter .symbolSummary li.skipped:before {
+ color: #bababa;
+ content: "\02022";
+}
+#HTMLReporter .symbolSummary li.pending {
+ line-height: 11px;
+}
+#HTMLReporter .symbolSummary li.pending:before {
+ color: #aaaaaa;
+ content: "-";
+}
+#HTMLReporter .exceptions {
+ color: #fff;
+ float: right;
+ margin-top: 5px;
+ margin-right: 5px;
+}
+#HTMLReporter .bar {
+ line-height: 28px;
+ font-size: 14px;
+ display: block;
+ color: #eee;
+}
+#HTMLReporter .runningAlert {
+ background-color: #666666;
+}
+#HTMLReporter .skippedAlert {
+ background-color: #aaaaaa;
+}
+#HTMLReporter .skippedAlert:first-child {
+ background-color: #333333;
+}
+#HTMLReporter .skippedAlert:hover {
text-decoration: none;
+ color: white;
+ text-decoration: underline;
}
-
-.jasmine_reporter {
- margin: 0 5px;
+#HTMLReporter .passingAlert {
+ background-color: #a6b779;
+}
+#HTMLReporter .passingAlert:first-child {
+ background-color: #5e7d00;
+}
+#HTMLReporter .failingAlert {
+ background-color: #cf867e;
+}
+#HTMLReporter .failingAlert:first-child {
+ background-color: #b03911;
+}
+#HTMLReporter .results {
+ margin-top: 14px;
+}
+#HTMLReporter #details {
+ display: none;
+}
+#HTMLReporter .resultsMenu,
+#HTMLReporter .resultsMenu a {
+ background-color: #fff;
+ color: #333333;
+}
+#HTMLReporter.showDetails .summaryMenuItem {
+ font-weight: normal;
+ text-decoration: inherit;
+}
+#HTMLReporter.showDetails .summaryMenuItem:hover {
+ text-decoration: underline;
+}
+#HTMLReporter.showDetails .detailsMenuItem {
+ font-weight: bold;
+ text-decoration: underline;
+}
+#HTMLReporter.showDetails .summary {
+ display: none;
+}
+#HTMLReporter.showDetails #details {
+ display: block;
+}
+#HTMLReporter .summaryMenuItem {
+ font-weight: bold;
+ text-decoration: underline;
+}
+#HTMLReporter .summary {
+ margin-top: 14px;
+}
+#HTMLReporter .summary .suite .suite,
+#HTMLReporter .summary .specSummary {
+ margin-left: 14px;
+}
+#HTMLReporter .summary .specSummary.passed a {
+ color: #5e7d00;
+}
+#HTMLReporter .summary .specSummary.failed a {
+ color: #b03911;
+}
+#HTMLReporter .description + .suite {
+ margin-top: 0;
+}
+#HTMLReporter .suite {
+ margin-top: 14px;
+}
+#HTMLReporter .suite a {
+ color: #333333;
+}
+#HTMLReporter #details .specDetail {
+ margin-bottom: 28px;
+}
+#HTMLReporter #details .specDetail .description {
+ display: block;
+ color: white;
+ background-color: #b03911;
+}
+#HTMLReporter .resultMessage {
+ padding-top: 14px;
+ color: #333333;
+}
+#HTMLReporter .resultMessage span.result {
+ display: block;
+}
+#HTMLReporter .stackTrace {
+ margin: 5px 0 0 0;
+ max-height: 224px;
+ overflow: auto;
+ line-height: 18px;
+ color: #666666;
+ border: 1px solid #ddd;
+ background: white;
+ white-space: pre;
}
-.banner {
+#TrivialReporter {
+ padding: 8px 13px;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ overflow-y: scroll;
+ background-color: white;
+ font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial",
+ sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/
+}
+#TrivialReporter a:visited,
+#TrivialReporter a {
+ color: #303;
+}
+#TrivialReporter a:hover,
+#TrivialReporter a:active {
+ color: blue;
+}
+#TrivialReporter .run_spec {
+ float: right;
+ padding-right: 5px;
+ font-size: 0.8em;
+ text-decoration: none;
+}
+#TrivialReporter .banner {
color: #303;
background-color: #fef;
padding: 5px;
}
-
-.logo {
+#TrivialReporter .logo {
float: left;
font-size: 1.1em;
padding-left: 5px;
}
-
-.logo .version {
- font-size: .6em;
+#TrivialReporter .logo .version {
+ font-size: 0.6em;
padding-left: 1em;
}
-
-.runner.running {
+#TrivialReporter .runner.running {
background-color: yellow;
}
-
-
-.options {
+#TrivialReporter .options {
text-align: right;
- font-size: .8em;
+ font-size: 0.8em;
}
-
-
-
-
-.suite {
+#TrivialReporter .suite {
border: 1px outset gray;
margin: 5px 0;
padding-left: 1em;
}
-
-.suite .suite {
- margin: 5px;
+#TrivialReporter .suite .suite {
+ margin: 5px;
}
-
-.suite.passed {
+#TrivialReporter .suite.passed {
background-color: #dfd;
}
-
-.suite.failed {
+#TrivialReporter .suite.failed {
background-color: #fdd;
}
-
-.spec {
+#TrivialReporter .spec {
margin: 5px;
padding-left: 1em;
clear: both;
}
-
-.spec.failed, .spec.passed, .spec.skipped {
+#TrivialReporter .spec.failed,
+#TrivialReporter .spec.passed,
+#TrivialReporter .spec.skipped {
padding-bottom: 5px;
border: 1px solid gray;
}
-
-.spec.failed {
+#TrivialReporter .spec.failed {
background-color: #fbb;
border-color: red;
}
-
-.spec.passed {
+#TrivialReporter .spec.passed {
background-color: #bfb;
border-color: green;
}
-
-.spec.skipped {
+#TrivialReporter .spec.skipped {
background-color: #bbb;
}
-
-.messages {
+#TrivialReporter .messages {
border-left: 1px dashed gray;
padding-left: 1em;
padding-right: 1em;
}
-
-.passed {
+#TrivialReporter .passed {
background-color: #cfc;
display: none;
}
-
-.failed {
+#TrivialReporter .failed {
background-color: #fbb;
}
-
-.skipped {
+#TrivialReporter .skipped {
color: #777;
background-color: #eee;
display: none;
}
-
-
-/*.resultMessage {*/
- /*white-space: pre;*/
-/*}*/
-
-.resultMessage span.result {
+#TrivialReporter .resultMessage span.result {
display: block;
line-height: 2em;
color: black;
}
-
-.resultMessage .mismatch {
+#TrivialReporter .resultMessage .mismatch {
color: black;
}
-
-.stackTrace {
+#TrivialReporter .stackTrace {
white-space: pre;
- font-size: .8em;
+ font-size: 0.8em;
margin-left: 10px;
max-height: 5em;
overflow: auto;
@@ -141,24 +330,19 @@ body {
padding: 1em;
background: #eef;
}
-
-.finished-at {
+#TrivialReporter .finished-at {
padding-left: 1em;
- font-size: .6em;
+ font-size: 0.6em;
}
-
-.show-passed .passed,
-.show-skipped .skipped {
+#TrivialReporter.show-passed .passed,
+#TrivialReporter.show-skipped .skipped {
display: block;
}
-
-
-#jasmine_content {
- position:fixed;
+#TrivialReporter #jasmine_content {
+ position: fixed;
right: 100%;
}
-
-.runner {
+#TrivialReporter .runner {
border: 1px solid gray;
display: block;
margin: 5px 0;
diff --git a/lib/jasmine/jasmine.js b/lib/jasmine/jasmine.js
index 3ace3bc40..9e93acda0 100644
--- a/lib/jasmine/jasmine.js
+++ b/lib/jasmine/jasmine.js
@@ -1,14 +1,16 @@
+var isCommonJS = typeof window == "undefined" && typeof exports == "object";
+
/**
* Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
*
* @namespace
*/
var jasmine = {};
-
+if (isCommonJS) exports.jasmine = jasmine;
/**
* @private
*/
-jasmine.unimplementedMethod_ = function() {
+jasmine.unimplementedMethod_ = function () {
throw new Error("unimplemented method");
};
@@ -20,18 +22,36 @@ jasmine.unimplementedMethod_ = function() {
*/
jasmine.undefined = jasmine.___undefined___;
+/**
+ * Show diagnostic messages in the console if set to true
+ *
+ */
+jasmine.VERBOSE = false;
+
/**
* Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
*
*/
jasmine.DEFAULT_UPDATE_INTERVAL = 250;
+/**
+ * Maximum levels of nesting that will be included when an object is pretty-printed
+ */
+jasmine.MAX_PRETTY_PRINT_DEPTH = 40;
+
/**
* Default timeout interval in milliseconds for waitsFor() blocks.
*/
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
-jasmine.getGlobal = function() {
+/**
+ * By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite.
+ * Set to false to let the exception bubble up in the browser.
+ *
+ */
+jasmine.CATCH_EXCEPTIONS = true;
+
+jasmine.getGlobal = function () {
function getGlobal() {
return this;
}
@@ -47,10 +67,10 @@ jasmine.getGlobal = function() {
* @param base {Object} bound 'this' for the function
* @param name {Function} function to find
*/
-jasmine.bindOriginal_ = function(base, name) {
+jasmine.bindOriginal_ = function (base, name) {
var original = base[name];
if (original.apply) {
- return function() {
+ return function () {
return original.apply(base, arguments);
};
} else {
@@ -59,20 +79,26 @@ jasmine.bindOriginal_ = function(base, 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.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';
+jasmine.MessageResult = function (values) {
+ this.type = "log";
this.values = values;
this.trace = new Error(); // todo: test better
};
-jasmine.MessageResult.prototype.toString = function() {
+jasmine.MessageResult.prototype.toString = function () {
var text = "";
- for(var i = 0; i < this.values.length; i++) {
+ for (var i = 0; i < this.values.length; i++) {
if (i > 0) text += " ";
if (jasmine.isString_(this.values[i])) {
text += this.values[i];
@@ -83,15 +109,16 @@ jasmine.MessageResult.prototype.toString = function() {
return text;
};
-jasmine.ExpectationResult = function(params) {
- this.type = 'expect';
+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.message = this.passed_ ? 'Passed.' : params.message;
- this.trace = this.passed_ ? '' : new Error(this.message);
+ var trace = params.trace || new Error(this.message);
+ this.trace = this.passed_ ? "" : trace;
};
jasmine.ExpectationResult.prototype.toString = function () {
@@ -105,8 +132,9 @@ jasmine.ExpectationResult.prototype.passed = function () {
/**
* Getter for the Jasmine environment. Ensures one gets created
*/
-jasmine.getEnv = function() {
- return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
+jasmine.getEnv = function () {
+ var env = (jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env());
+ return env;
};
/**
@@ -115,8 +143,8 @@ jasmine.getEnv = function() {
* @param value
* @returns {Boolean}
*/
-jasmine.isArray_ = function(value) {
- return jasmine.isA_("Array", value);
+jasmine.isArray_ = function (value) {
+ return jasmine.isA_("Array", value);
};
/**
@@ -125,7 +153,7 @@ jasmine.isArray_ = function(value) {
* @param value
* @returns {Boolean}
*/
-jasmine.isString_ = function(value) {
+jasmine.isString_ = function (value) {
return jasmine.isA_("String", value);
};
@@ -135,7 +163,7 @@ jasmine.isString_ = function(value) {
* @param value
* @returns {Boolean}
*/
-jasmine.isNumber_ = function(value) {
+jasmine.isNumber_ = function (value) {
return jasmine.isA_("Number", value);
};
@@ -146,8 +174,8 @@ jasmine.isNumber_ = function(value) {
* @param value
* @returns {Boolean}
*/
-jasmine.isA_ = function(typeName, value) {
- return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
+jasmine.isA_ = function (typeName, value) {
+ return Object.prototype.toString.apply(value) === "[object " + typeName + "]";
};
/**
@@ -156,7 +184,7 @@ jasmine.isA_ = function(typeName, value) {
* @param value {Object} an object to be outputted
* @returns {String}
*/
-jasmine.pp = function(value) {
+jasmine.pp = function (value) {
var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
stringPrettyPrinter.format(value);
return stringPrettyPrinter.string;
@@ -168,8 +196,8 @@ jasmine.pp = function(value) {
* @param {Object} obj object to check
* @returns {Boolean}
*/
-jasmine.isDomNode = function(obj) {
- return obj['nodeType'] > 0;
+jasmine.isDomNode = function (obj) {
+ return obj.nodeType > 0;
};
/**
@@ -182,10 +210,25 @@ jasmine.isDomNode = function(obj) {
* @param {Class} clazz
* @returns matchable object of the type clazz
*/
-jasmine.any = function(clazz) {
+jasmine.any = function (clazz) {
return new jasmine.Matchers.Any(clazz);
};
+/**
+ * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the
+ * attributes on the object.
+ *
+ * @example
+ * // don't care about any other attributes than foo.
+ * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"});
+ *
+ * @param sample {Object} sample
+ * @returns matchable object for the sample
+ */
+jasmine.objectContaining = function (sample) {
+ return new jasmine.Matchers.ObjectContaining(sample);
+};
+
/**
* Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
*
@@ -230,11 +273,11 @@ jasmine.any = function(clazz) {
* @see spyOn, jasmine.createSpy, jasmine.createSpyObj
* @param {String} name
*/
-jasmine.Spy = function(name) {
+jasmine.Spy = function (name) {
/**
* The name of the spy, if provided.
*/
- this.identity = name || 'unknown';
+ this.identity = name || "unknown";
/**
* Is this Object a spy?
*/
@@ -242,8 +285,7 @@ jasmine.Spy = function(name) {
/**
* The actual function this spy stubs.
*/
- this.plan = function() {
- };
+ this.plan = function () {};
/**
* Tracking of the most recent call to the spy.
* @example
@@ -278,7 +320,7 @@ jasmine.Spy = function(name) {
* // defining a spy on an existing property: foo.bar
* spyOn(foo, 'bar').andCallThrough();
*/
-jasmine.Spy.prototype.andCallThrough = function() {
+jasmine.Spy.prototype.andCallThrough = function () {
this.plan = this.originalValue;
return this;
};
@@ -295,8 +337,8 @@ jasmine.Spy.prototype.andCallThrough = function() {
*
* @param {Object} value
*/
-jasmine.Spy.prototype.andReturn = function(value) {
- this.plan = function() {
+jasmine.Spy.prototype.andReturn = function (value) {
+ this.plan = function () {
return value;
};
return this;
@@ -314,8 +356,8 @@ jasmine.Spy.prototype.andReturn = function(value) {
*
* @param {String} exceptionMsg
*/
-jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
- this.plan = function() {
+jasmine.Spy.prototype.andThrow = function (exceptionMsg) {
+ this.plan = function () {
throw exceptionMsg;
};
return this;
@@ -336,7 +378,7 @@ jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
*
* @param {Function} fakeFunc
*/
-jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
+jasmine.Spy.prototype.andCallFake = function (fakeFunc) {
this.plan = fakeFunc;
return this;
};
@@ -355,7 +397,7 @@ jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
*
* expect(foo.bar.callCount).toEqual(0);
*/
-jasmine.Spy.prototype.reset = function() {
+jasmine.Spy.prototype.reset = function () {
this.wasCalled = false;
this.callCount = 0;
this.argsForCall = [];
@@ -363,16 +405,15 @@ jasmine.Spy.prototype.reset = function() {
this.mostRecentCall = {};
};
-jasmine.createSpy = function(name) {
-
- var spyObj = function() {
+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});
+ spyObj.calls.push({ object: this, args: args });
return spyObj.plan.apply(this, arguments);
};
@@ -393,7 +434,7 @@ jasmine.createSpy = function(name) {
* @param {jasmine.Spy|Object} putativeSpy
* @returns {Boolean}
*/
-jasmine.isSpy = function(putativeSpy) {
+jasmine.isSpy = function (putativeSpy) {
return putativeSpy && putativeSpy.isSpy;
};
@@ -404,13 +445,15 @@ jasmine.isSpy = function(putativeSpy) {
* @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');
+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]);
+ obj[methodNames[i]] = jasmine.createSpy(baseName + "." + methodNames[i]);
}
return obj;
};
@@ -420,7 +463,7 @@ jasmine.createSpyObj = function(baseName, methodNames) {
*
* Be careful not to leave calls to jasmine.log
in production code.
*/
-jasmine.log = function() {
+jasmine.log = function () {
var spec = jasmine.getEnv().currentSpec;
spec.log.apply(spec, arguments);
};
@@ -438,11 +481,12 @@ jasmine.log = function() {
* @see jasmine.createSpy
* @param obj
* @param methodName
- * @returns a Jasmine spy that can be chained with all spy methods
+ * @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods
*/
-var spyOn = function(obj, methodName) {
+var spyOn = function (obj, methodName) {
return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
};
+if (isCommonJS) exports.spyOn = spyOn;
/**
* Creates a Jasmine spec that will be added to the current suite.
@@ -457,9 +501,10 @@ var spyOn = function(obj, methodName) {
* @param {String} desc description of this specification
* @param {Function} func defines the preconditions and expectations of the spec
*/
-var it = function(desc, func) {
+var it = function (desc, func) {
return jasmine.getEnv().it(desc, func);
};
+if (isCommonJS) exports.it = it;
/**
* Creates a disabled Jasmine spec.
@@ -469,9 +514,10 @@ var it = function(desc, func) {
* @param {String} desc description of this specification
* @param {Function} func defines the preconditions and expectations of the spec
*/
-var xit = function(desc, func) {
+var xit = function (desc, func) {
return jasmine.getEnv().xit(desc, func);
};
+if (isCommonJS) exports.xit = xit;
/**
* Starts a chain for a Jasmine expectation.
@@ -480,19 +526,22 @@ var xit = function(desc, func) {
* jasmine.Matchers functions.
*
* @param {Object} actual Actual value to test against and expected value
+ * @return {jasmine.Matchers}
*/
-var expect = function(actual) {
+var expect = function (actual) {
return jasmine.getEnv().currentSpec.expect(actual);
};
+if (isCommonJS) exports.expect = expect;
/**
* 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) {
+var runs = function (func) {
jasmine.getEnv().currentSpec.runs(func);
};
+if (isCommonJS) exports.runs = runs;
/**
* Waits a fixed time period before moving to the next block.
@@ -500,9 +549,10 @@ var runs = function(func) {
* @deprecated Use waitsFor() instead
* @param {Number} timeout milliseconds to wait
*/
-var waits = function(timeout) {
+var waits = function (timeout) {
jasmine.getEnv().currentSpec.waits(timeout);
};
+if (isCommonJS) exports.waits = waits;
/**
* Waits for the latchFunction to return true before proceeding to the next block.
@@ -511,9 +561,16 @@ var waits = function(timeout) {
* @param {String} optional_timeoutMessage
* @param {Number} optional_timeout
*/
-var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
- jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
+var waitsFor = function (
+ latchFunction,
+ optional_timeoutMessage,
+ optional_timeout
+) {
+ jasmine
+ .getEnv()
+ .currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
};
+if (isCommonJS) exports.waitsFor = waitsFor;
/**
* A function that is called before each spec in a suite.
@@ -522,9 +579,10 @@ var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout
*
* @param {Function} beforeEachFunction
*/
-var beforeEach = function(beforeEachFunction) {
+var beforeEach = function (beforeEachFunction) {
jasmine.getEnv().beforeEach(beforeEachFunction);
};
+if (isCommonJS) exports.beforeEach = beforeEach;
/**
* A function that is called after each spec in a suite.
@@ -533,9 +591,10 @@ var beforeEach = function(beforeEachFunction) {
*
* @param {Function} afterEachFunction
*/
-var afterEach = function(afterEachFunction) {
+var afterEach = function (afterEachFunction) {
jasmine.getEnv().afterEach(afterEachFunction);
};
+if (isCommonJS) exports.afterEach = afterEach;
/**
* Defines a suite of specifications.
@@ -552,9 +611,10 @@ var afterEach = function(afterEachFunction) {
* @param {String} description A string, usually the class under test.
* @param {Function} specDefinitions function that defines several specs.
*/
-var describe = function(description, specDefinitions) {
+var describe = function (description, specDefinitions) {
return jasmine.getEnv().describe(description, specDefinitions);
};
+if (isCommonJS) exports.describe = describe;
/**
* Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
@@ -562,31 +622,42 @@ var describe = function(description, specDefinitions) {
* @param {String} description A string, usually the class under test.
* @param {Function} specDefinitions function that defines several specs.
*/
-var xdescribe = function(description, specDefinitions) {
+var xdescribe = function (description, specDefinitions) {
return jasmine.getEnv().xdescribe(description, specDefinitions);
};
-
+if (isCommonJS) exports.xdescribe = xdescribe;
// 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;
+jasmine.XmlHttpRequest =
+ typeof XMLHttpRequest == "undefined"
+ ? function () {
+ function tryIt(f) {
+ try {
+ return f();
+ } catch (e) {}
+ return null;
+ }
+
+ var xhr =
+ tryIt(function () {
+ return new ActiveXObject("Msxml2.XMLHTTP.6.0");
+ }) ||
+ tryIt(function () {
+ return new ActiveXObject("Msxml2.XMLHTTP.3.0");
+ }) ||
+ tryIt(function () {
+ return new ActiveXObject("Msxml2.XMLHTTP");
+ }) ||
+ tryIt(function () {
+ return new ActiveXObject("Microsoft.XMLHTTP");
+ });
+
+ if (!xhr)
+ throw new Error("This browser does not support XMLHttpRequest.");
+
+ return xhr;
+ }
+ : XMLHttpRequest;
/**
* @namespace
*/
@@ -599,22 +670,20 @@ jasmine.util = {};
* @param {Function} childClass
* @param {Function} parentClass
*/
-jasmine.util.inherit = function(childClass, parentClass) {
+jasmine.util.inherit = function (childClass, parentClass) {
/**
* @private
*/
- var subclass = function() {
- };
+ var subclass = function () {};
subclass.prototype = parentClass.prototype;
- childClass.prototype = new subclass;
+ childClass.prototype = new subclass();
};
-jasmine.util.formatException = function(e) {
+jasmine.util.formatException = function (e) {
var lineNumber;
if (e.line) {
lineNumber = e.line;
- }
- else if (e.lineNumber) {
+ } else if (e.lineNumber) {
lineNumber = e.lineNumber;
}
@@ -622,34 +691,31 @@ jasmine.util.formatException = function(e) {
if (e.sourceURL) {
file = e.sourceURL;
- }
- else if (e.fileName) {
+ } else if (e.fileName) {
file = e.fileName;
}
- var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
+ var message = e.name && e.message ? e.name + ": " + e.message : e.toString();
if (file && lineNumber) {
- message += ' in ' + file + ' (line ' + lineNumber + ')';
+ message += " in " + file + " (line " + lineNumber + ")";
}
return message;
};
-jasmine.util.htmlEscape = function(str) {
+jasmine.util.htmlEscape = function (str) {
if (!str) return str;
- return str.replace(/&/g, '&')
- .replace(//g, '>');
+ return str.replace(/&/g, "&").replace(//g, ">");
};
-jasmine.util.argsToArray = function(args) {
+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) {
+jasmine.util.extend = function (destination, source) {
for (var property in source) destination[property] = source[property];
return destination;
};
@@ -659,7 +725,7 @@ jasmine.util.extend = function(destination, source) {
*
* @constructor
*/
-jasmine.Env = function() {
+jasmine.Env = function () {
this.currentSpec = null;
this.currentSuite = null;
this.currentRunner_ = new jasmine.Runner(this);
@@ -669,7 +735,7 @@ jasmine.Env = function() {
this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
this.lastUpdate = 0;
- this.specFilter = function() {
+ this.specFilter = function () {
return true;
};
@@ -678,7 +744,7 @@ jasmine.Env = function() {
this.equalityTesters_ = [];
// wrap matchers
- this.matchersClass = function() {
+ this.matchersClass = function () {
jasmine.Matchers.apply(this, arguments);
};
jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
@@ -686,7 +752,6 @@ jasmine.Env = function() {
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;
@@ -699,20 +764,25 @@ jasmine.Env.prototype.version = function () {
if (jasmine.version_) {
return jasmine.version_;
} else {
- throw new Error('Version not set');
+ 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 {
+jasmine.Env.prototype.versionString = function () {
+ if (!jasmine.version_) {
return "version unknown";
}
+
+ var version = this.version();
+ var versionString = version.major + "." + version.minor + "." + version.build;
+ if (version.release_candidate) {
+ versionString += ".rc" + version.release_candidate;
+ }
+ versionString += " revision " + version.revision;
+ return versionString;
};
/**
@@ -733,16 +803,21 @@ jasmine.Env.prototype.nextSuiteId = function () {
* 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) {
+jasmine.Env.prototype.addReporter = function (reporter) {
this.reporter.addReporter(reporter);
};
-jasmine.Env.prototype.execute = function() {
+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);
+jasmine.Env.prototype.describe = function (description, specDefinitions) {
+ var suite = new jasmine.Suite(
+ this,
+ description,
+ specDefinitions,
+ this.currentSuite
+ );
var parentSuite = this.currentSuite;
if (parentSuite) {
@@ -756,22 +831,22 @@ jasmine.Env.prototype.describe = function(description, specDefinitions) {
var declarationError = null;
try {
specDefinitions.call(suite);
- } catch(e) {
+ } catch (e) {
declarationError = e;
}
- this.currentSuite = parentSuite;
-
if (declarationError) {
- this.it("encountered a declaration exception", function() {
+ this.it("encountered a declaration exception", function () {
throw declarationError;
});
}
+ this.currentSuite = parentSuite;
+
return suite;
};
-jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
+jasmine.Env.prototype.beforeEach = function (beforeEachFunction) {
if (this.currentSuite) {
this.currentSuite.beforeEach(beforeEachFunction);
} else {
@@ -783,23 +858,21 @@ jasmine.Env.prototype.currentRunner = function () {
return this.currentRunner_;
};
-jasmine.Env.prototype.afterEach = function(afterEachFunction) {
+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) {
+jasmine.Env.prototype.xdescribe = function (desc, specDefinitions) {
return {
- execute: function() {
- }
+ execute: function () {},
};
};
-jasmine.Env.prototype.it = function(description, func) {
+jasmine.Env.prototype.it = function (description, func) {
var spec = new jasmine.Spec(this, this.currentSuite, description);
this.currentSuite.add(spec);
this.currentSpec = spec;
@@ -811,40 +884,109 @@ jasmine.Env.prototype.it = function(description, func) {
return spec;
};
-jasmine.Env.prototype.xit = function(desc, func) {
+jasmine.Env.prototype.xit = function (desc, func) {
return {
id: this.nextSpecId(),
- runs: function() {
- }
+ runs: function () {},
};
};
-jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
- if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
+jasmine.Env.prototype.compareRegExps_ = function (
+ a,
+ b,
+ mismatchKeys,
+ mismatchValues
+) {
+ if (a.source != b.source)
+ mismatchValues.push(
+ "expected pattern /" +
+ b.source +
+ "/ is not equal to the pattern /" +
+ a.source +
+ "/"
+ );
+
+ if (a.ignoreCase != b.ignoreCase)
+ mismatchValues.push(
+ "expected modifier i was" +
+ (b.ignoreCase ? " " : " not ") +
+ "set and does not equal the origin modifier"
+ );
+
+ if (a.global != b.global)
+ mismatchValues.push(
+ "expected modifier g was" +
+ (b.global ? " " : " not ") +
+ "set and does not equal the origin modifier"
+ );
+
+ if (a.multiline != b.multiline)
+ mismatchValues.push(
+ "expected modifier m was" +
+ (b.multiline ? " " : " not ") +
+ "set and does not equal the origin modifier"
+ );
+
+ if (a.sticky != b.sticky)
+ mismatchValues.push(
+ "expected modifier y was" +
+ (b.sticky ? " " : " not ") +
+ "set and does not equal the origin modifier"
+ );
+
+ return mismatchValues.length === 0;
+};
+
+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;
+ 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.");
+ 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.");
+ mismatchKeys.push(
+ "expected missing key '" + property + "', but present in actual."
+ );
}
}
for (property in b) {
- if (property == '__Jasmine_been_here_before__') continue;
+ 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.");
+ 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."
+ );
}
}
@@ -854,10 +996,10 @@ jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchVal
delete a.__Jasmine_been_here_before__;
delete b.__Jasmine_been_here_before__;
- return (mismatchKeys.length == 0 && mismatchValues.length == 0);
+ return mismatchKeys.length === 0 && mismatchValues.length === 0;
};
-jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
+jasmine.Env.prototype.equals_ = function (a, b, mismatchKeys, mismatchValues) {
mismatchKeys = mismatchKeys || [];
mismatchValues = mismatchValues || [];
@@ -869,8 +1011,13 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
if (a === b) return true;
- if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
- return (a == jasmine.undefined && b == jasmine.undefined);
+ 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)) {
@@ -881,20 +1028,32 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
return a.getTime() == b.getTime();
}
- if (a instanceof jasmine.Matchers.Any) {
+ if (a.jasmineMatches) {
+ return a.jasmineMatches(b);
+ }
+
+ if (b.jasmineMatches) {
+ return b.jasmineMatches(a);
+ }
+
+ if (a instanceof jasmine.Matchers.ObjectContaining) {
return a.matches(b);
}
- if (b instanceof jasmine.Matchers.Any) {
+ if (b instanceof jasmine.Matchers.ObjectContaining) {
return b.matches(a);
}
if (jasmine.isString_(a) && jasmine.isString_(b)) {
- return (a == b);
+ return a == b;
}
if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
- return (a == b);
+ return a == b;
+ }
+
+ if (a instanceof RegExp && b instanceof RegExp) {
+ return this.compareRegExps_(a, b, mismatchKeys, mismatchValues);
}
if (typeof a === "object" && typeof b === "object") {
@@ -902,10 +1061,10 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
}
//Straight check
- return (a === b);
+ return a === b;
};
-jasmine.Env.prototype.contains_ = function(haystack, needle) {
+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;
@@ -915,39 +1074,32 @@ jasmine.Env.prototype.contains_ = function(haystack, needle) {
return haystack.indexOf(needle) >= 0;
};
-jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
+jasmine.Env.prototype.addEqualityTester = function (equalityTester) {
this.equalityTesters_.push(equalityTester);
};
/** No-op base class for Jasmine reporters.
*
* @constructor
*/
-jasmine.Reporter = function() {
-};
+jasmine.Reporter = function () {};
//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
-};
+jasmine.Reporter.prototype.reportRunnerStarting = function (runner) {};
//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
-};
+jasmine.Reporter.prototype.reportRunnerResults = function (runner) {};
//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
-};
+jasmine.Reporter.prototype.reportSuiteResults = function (suite) {};
//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
-};
+jasmine.Reporter.prototype.reportSpecStarting = function (spec) {};
//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.reportSpecResults = function(spec) {
-};
+jasmine.Reporter.prototype.reportSpecResults = function (spec) {};
//noinspection JSUnusedLocalSymbols
-jasmine.Reporter.prototype.log = function(str) {
-};
+jasmine.Reporter.prototype.log = function (str) {};
/**
* Blocks are functions with executable code that make up a spec.
@@ -957,17 +1109,21 @@ jasmine.Reporter.prototype.log = function(str) {
* @param {Function} func
* @param {jasmine.Spec} spec
*/
-jasmine.Block = function(env, func, spec) {
+jasmine.Block = function (env, func, spec) {
this.env = env;
this.func = func;
this.spec = spec;
};
-jasmine.Block.prototype.execute = function(onComplete) {
- try {
+jasmine.Block.prototype.execute = function (onComplete) {
+ if (!jasmine.CATCH_EXCEPTIONS) {
this.func.apply(this.spec);
- } catch (e) {
- this.spec.fail(e);
+ } else {
+ try {
+ this.func.apply(this.spec);
+ } catch (e) {
+ this.spec.fail(e);
+ }
}
onComplete();
};
@@ -975,14 +1131,14 @@ jasmine.Block.prototype.execute = function(onComplete) {
*
* @constructor
*/
-jasmine.JsApiReporter = function() {
+jasmine.JsApiReporter = function () {
this.started = false;
this.finished = false;
this.suites_ = [];
this.results_ = {};
};
-jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
+jasmine.JsApiReporter.prototype.reportRunnerStarting = function (runner) {
this.started = true;
var suites = runner.topLevelSuites();
for (var i = 0; i < suites.length; i++) {
@@ -991,19 +1147,19 @@ jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
}
};
-jasmine.JsApiReporter.prototype.suites = function() {
+jasmine.JsApiReporter.prototype.suites = function () {
return this.suites_;
};
-jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
+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: []
+ type: isSuite ? "suite" : "spec",
+ children: [],
};
-
+
if (isSuite) {
var children = suiteOrSpec.children();
for (var i = 0; i < children.length; i++) {
@@ -1013,36 +1169,34 @@ jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
return summary;
};
-jasmine.JsApiReporter.prototype.results = function() {
+jasmine.JsApiReporter.prototype.results = function () {
return this.results_;
};
-jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
+jasmine.JsApiReporter.prototype.resultsForSpec = function (specId) {
return this.results_[specId];
};
//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
+jasmine.JsApiReporter.prototype.reportRunnerResults = function (runner) {
this.finished = true;
};
//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
-};
+jasmine.JsApiReporter.prototype.reportSuiteResults = function (suite) {};
//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
+jasmine.JsApiReporter.prototype.reportSpecResults = function (spec) {
this.results_[spec.id] = {
messages: spec.results().getItems(),
- result: spec.results().failedCount > 0 ? "failed" : "passed"
+ result: spec.results().failedCount > 0 ? "failed" : "passed",
};
};
//noinspection JSUnusedLocalSymbols
-jasmine.JsApiReporter.prototype.log = function(str) {
-};
+jasmine.JsApiReporter.prototype.log = function (str) {};
-jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
+jasmine.JsApiReporter.prototype.resultsForSpecs = function (specIds) {
var results = {};
for (var i = 0; i < specIds.length; i++) {
var specId = specIds[i];
@@ -1051,25 +1205,31 @@ jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
return results;
};
-jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
+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,
+ 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
- }
+ stack:
+ resultMessage.passed && !resultMessage.passed()
+ ? resultMessage.trace.stack
+ : jasmine.undefined,
+ },
});
}
return {
- result : result.result,
- messages : summaryMessages
+ result: result.result,
+ messages: summaryMessages,
};
};
@@ -1079,7 +1239,7 @@ jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
* @param actual
* @param {jasmine.Spec} spec
*/
-jasmine.Matchers = function(env, actual, spec, opt_isNot) {
+jasmine.Matchers = function (env, actual, spec, opt_isNot) {
this.env = env;
this.actual = actual;
this.spec = spec;
@@ -1088,25 +1248,36 @@ jasmine.Matchers = function(env, actual, spec, opt_isNot) {
};
// 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!");
+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.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) {
+jasmine.Matchers.wrapInto_ = function (prototype, matchersClass) {
for (var methodName in prototype) {
- if (methodName == 'report') continue;
+ if (methodName == "report") continue;
var orig = prototype[methodName];
- matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
+ matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(
+ methodName,
+ orig
+ );
}
};
-jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
- return function() {
+jasmine.Matchers.matcherFn_ = function (matcherName, matcherFunction) {
+ return function () {
var matcherArgs = jasmine.util.argsToArray(arguments);
var result = matcherFunction.apply(this, arguments);
@@ -1124,8 +1295,14 @@ jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
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;
+ 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 += ",";
@@ -1140,21 +1317,18 @@ jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
passed: result,
expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
actual: this.actual,
- message: message
+ message: message,
});
this.spec.addMatcherResult(expectationResult);
return jasmine.undefined;
};
};
-
-
-
/**
* toBe: compares the actual to the expected using ===
* @param expected
*/
-jasmine.Matchers.prototype.toBe = function(expected) {
+jasmine.Matchers.prototype.toBe = function (expected) {
return this.actual === expected;
};
@@ -1163,7 +1337,7 @@ jasmine.Matchers.prototype.toBe = function(expected) {
* @param expected
* @deprecated as of 1.0. Use not.toBe() instead.
*/
-jasmine.Matchers.prototype.toNotBe = function(expected) {
+jasmine.Matchers.prototype.toNotBe = function (expected) {
return this.actual !== expected;
};
@@ -1172,16 +1346,16 @@ jasmine.Matchers.prototype.toNotBe = function(expected) {
*
* @param expected
*/
-jasmine.Matchers.prototype.toEqual = function(expected) {
+jasmine.Matchers.prototype.toEqual = function (expected) {
return this.env.equals_(this.actual, expected);
};
/**
* toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
* @param expected
- * @deprecated as of 1.0. Use not.toNotEqual() instead.
+ * @deprecated as of 1.0. Use not.toEqual() instead.
*/
-jasmine.Matchers.prototype.toNotEqual = function(expected) {
+jasmine.Matchers.prototype.toNotEqual = function (expected) {
return !this.env.equals_(this.actual, expected);
};
@@ -1191,7 +1365,7 @@ jasmine.Matchers.prototype.toNotEqual = function(expected) {
*
* @param expected
*/
-jasmine.Matchers.prototype.toMatch = function(expected) {
+jasmine.Matchers.prototype.toMatch = function (expected) {
return new RegExp(expected).test(this.actual);
};
@@ -1200,63 +1374,74 @@ jasmine.Matchers.prototype.toMatch = function(expected) {
* @param expected
* @deprecated as of 1.0. Use not.toMatch() instead.
*/
-jasmine.Matchers.prototype.toNotMatch = function(expected) {
- return !(new RegExp(expected).test(this.actual));
+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);
+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);
+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);
+jasmine.Matchers.prototype.toBeNull = function () {
+ return this.actual === null;
+};
+
+/**
+ * Matcher that compares the actual to NaN.
+ */
+jasmine.Matchers.prototype.toBeNaN = function () {
+ this.message = function () {
+ return ["Expected " + jasmine.pp(this.actual) + " to be NaN."];
+ };
+
+ return this.actual !== this.actual;
};
/**
* Matcher that boolean not-nots the actual.
*/
-jasmine.Matchers.prototype.toBeTruthy = function() {
+jasmine.Matchers.prototype.toBeTruthy = function () {
return !!this.actual;
};
-
/**
* Matcher that boolean nots the actual.
*/
-jasmine.Matchers.prototype.toBeFalsy = function() {
+jasmine.Matchers.prototype.toBeFalsy = function () {
return !this.actual;
};
-
/**
* Matcher that checks to see if the actual, a Jasmine spy, was called.
*/
-jasmine.Matchers.prototype.toHaveBeenCalled = function() {
+jasmine.Matchers.prototype.toHaveBeenCalled = function () {
if (arguments.length > 0) {
- throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
+ 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) + '.');
+ throw new Error("Expected a spy, but got " + jasmine.pp(this.actual) + ".");
}
- this.message = function() {
+ this.message = function () {
return [
"Expected spy " + this.actual.identity + " to have been called.",
- "Expected spy " + this.actual.identity + " not to have been called."
+ "Expected spy " + this.actual.identity + " not to have been called.",
];
};
@@ -1264,26 +1449,27 @@ jasmine.Matchers.prototype.toHaveBeenCalled = function() {
};
/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
-jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
+jasmine.Matchers.prototype.wasCalled =
+ jasmine.Matchers.prototype.toHaveBeenCalled;
/**
* Matcher that checks to see if the actual, a Jasmine spy, was not called.
*
* @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
*/
-jasmine.Matchers.prototype.wasNotCalled = function() {
+jasmine.Matchers.prototype.wasNotCalled = function () {
if (arguments.length > 0) {
- throw new Error('wasNotCalled does not take arguments');
+ 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) + '.');
+ throw new Error("Expected a spy, but got " + jasmine.pp(this.actual) + ".");
}
- this.message = function() {
+ this.message = function () {
return [
"Expected spy " + this.actual.identity + " to not have been called.",
- "Expected spy " + this.actual.identity + " to have been called."
+ "Expected spy " + this.actual.identity + " to have been called.",
];
};
@@ -1296,44 +1482,61 @@ jasmine.Matchers.prototype.wasNotCalled = function() {
* @example
*
*/
-jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
+jasmine.Matchers.prototype.toHaveBeenCalledWith = function () {
var expectedArgs = jasmine.util.argsToArray(arguments);
if (!jasmine.isSpy(this.actual)) {
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
- }
- this.message = function() {
- if (this.actual.callCount == 0) {
- // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
- return [
- "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
- "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
- ];
+ throw new Error("Expected a spy, but got " + jasmine.pp(this.actual) + ".");
+ }
+ this.message = function () {
+ var invertedMessage =
+ "Expected spy " +
+ this.actual.identity +
+ " not to have been called with " +
+ jasmine.pp(expectedArgs) +
+ " but it was.";
+ var positiveMessage = "";
+ if (this.actual.callCount === 0) {
+ positiveMessage =
+ "Expected spy " +
+ this.actual.identity +
+ " 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),
- "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
- ];
+ positiveMessage =
+ "Expected spy " +
+ this.actual.identity +
+ " to have been called with " +
+ jasmine.pp(expectedArgs) +
+ " but actual calls were " +
+ jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, "");
}
+ return [positiveMessage, invertedMessage];
};
return this.env.contains_(this.actual.argsForCall, expectedArgs);
};
/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
-jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
+jasmine.Matchers.prototype.wasCalledWith =
+ jasmine.Matchers.prototype.toHaveBeenCalledWith;
/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
-jasmine.Matchers.prototype.wasNotCalledWith = function() {
+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) + '.');
+ throw new Error("Expected a spy, but got " + jasmine.pp(this.actual) + ".");
}
- this.message = function() {
+ this.message = function () {
return [
- "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
- "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
- ]
+ "Expected spy not to have been called with " +
+ jasmine.pp(expectedArgs) +
+ " but it was",
+ "Expected spy to have been called with " +
+ jasmine.pp(expectedArgs) +
+ " but it was",
+ ];
};
return !this.env.contains_(this.actual.argsForCall, expectedArgs);
@@ -1344,7 +1547,7 @@ jasmine.Matchers.prototype.wasNotCalledWith = function() {
*
* @param {Object} expected
*/
-jasmine.Matchers.prototype.toContain = function(expected) {
+jasmine.Matchers.prototype.toContain = function (expected) {
return this.env.contains_(this.actual, expected);
};
@@ -1352,30 +1555,44 @@ jasmine.Matchers.prototype.toContain = function(expected) {
* Matcher that checks that the expected item is NOT an element in the actual Array.
*
* @param {Object} expected
- * @deprecated as of 1.0. Use not.toNotContain() instead.
+ * @deprecated as of 1.0. Use not.toContain() instead.
*/
-jasmine.Matchers.prototype.toNotContain = function(expected) {
+jasmine.Matchers.prototype.toNotContain = function (expected) {
return !this.env.contains_(this.actual, expected);
};
-jasmine.Matchers.prototype.toBeLessThan = function(expected) {
+jasmine.Matchers.prototype.toBeLessThan = function (expected) {
return this.actual < expected;
};
-jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
+jasmine.Matchers.prototype.toBeGreaterThan = function (expected) {
return this.actual > expected;
};
+/**
+ * Matcher that checks that the expected item is equal to the actual item
+ * up to a given level of decimal precision (default 2).
+ *
+ * @param {Number} expected
+ * @param {Number} precision, as number of decimal places
+ */
+jasmine.Matchers.prototype.toBeCloseTo = function (expected, precision) {
+ if (!(precision === 0)) {
+ precision = precision || 2;
+ }
+ return Math.abs(expected - this.actual) < Math.pow(10, -precision) / 2;
+};
+
/**
* Matcher that checks that the expected exception was thrown by the actual.
*
- * @param {String} expected
+ * @param {String} [expected]
*/
-jasmine.Matchers.prototype.toThrow = function(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');
+ if (typeof this.actual != "function") {
+ throw new Error("Actual is not a function");
}
try {
this.actual();
@@ -1383,14 +1600,31 @@ jasmine.Matchers.prototype.toThrow = function(expected) {
exception = e;
}
if (exception) {
- result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
+ result =
+ expected === jasmine.undefined ||
+ this.env.equals_(
+ exception.message || exception,
+ expected.message || expected
+ );
}
var not = this.isNot ? "not " : "";
- this.message = function() {
- if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
- return ["Expected function " + not + "to throw", expected ? expected.message || expected : " an exception", ", but it threw", exception.message || exception].join(' ');
+ this.message = function () {
+ if (
+ exception &&
+ (expected === jasmine.undefined ||
+ !this.env.equals_(
+ exception.message || exception,
+ expected.message || expected
+ ))
+ ) {
+ return [
+ "Expected function " + not + "to throw",
+ expected ? expected.message || expected : "an exception",
+ ", but it threw",
+ exception.message || exception,
+ ].join(" ");
} else {
return "Expected function to throw an exception.";
}
@@ -1399,59 +1633,315 @@ jasmine.Matchers.prototype.toThrow = function(expected) {
return result;
};
-jasmine.Matchers.Any = function(expectedClass) {
+jasmine.Matchers.Any = function (expectedClass) {
this.expectedClass = expectedClass;
};
-jasmine.Matchers.Any.prototype.matches = function(other) {
+jasmine.Matchers.Any.prototype.jasmineMatches = function (other) {
if (this.expectedClass == String) {
- return typeof other == 'string' || other instanceof String;
+ return typeof other == "string" || other instanceof String;
}
if (this.expectedClass == Number) {
- return typeof other == 'number' || other instanceof Number;
+ return typeof other == "number" || other instanceof Number;
}
if (this.expectedClass == Function) {
- return typeof other == 'function' || other instanceof Function;
+ return typeof other == "function" || other instanceof Function;
}
if (this.expectedClass == Object) {
- return typeof other == 'object';
+ return typeof other == "object";
}
return other instanceof this.expectedClass;
};
-jasmine.Matchers.Any.prototype.toString = function() {
- return '';
+jasmine.Matchers.Any.prototype.jasmineToString = function () {
+ return "";
+};
+
+jasmine.Matchers.ObjectContaining = function (sample) {
+ this.sample = sample;
+};
+
+jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function (
+ other,
+ mismatchKeys,
+ mismatchValues
+) {
+ mismatchKeys = mismatchKeys || [];
+ mismatchValues = mismatchValues || [];
+
+ var env = jasmine.getEnv();
+
+ var hasKey = function (obj, keyName) {
+ return obj != null && obj[keyName] !== jasmine.undefined;
+ };
+
+ for (var property in this.sample) {
+ if (!hasKey(other, property) && hasKey(this.sample, property)) {
+ mismatchKeys.push(
+ "expected has key '" + property + "', but missing from actual."
+ );
+ } else if (
+ !env.equals_(
+ this.sample[property],
+ other[property],
+ mismatchKeys,
+ mismatchValues
+ )
+ ) {
+ mismatchValues.push(
+ "'" +
+ property +
+ "' was '" +
+ (other[property]
+ ? jasmine.util.htmlEscape(other[property].toString())
+ : other[property]) +
+ "' in expected, but was '" +
+ (this.sample[property]
+ ? jasmine.util.htmlEscape(this.sample[property].toString())
+ : this.sample[property]) +
+ "' in actual."
+ );
+ }
+ }
+
+ return mismatchKeys.length === 0 && mismatchValues.length === 0;
+};
+
+jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
+ return "";
+};
+// 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);
+ }
};
/**
* @constructor
*/
-jasmine.MultiReporter = function() {
+jasmine.MultiReporter = function () {
this.subReporters_ = [];
};
jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
-jasmine.MultiReporter.prototype.addReporter = function(reporter) {
+jasmine.MultiReporter.prototype.addReporter = function (reporter) {
this.subReporters_.push(reporter);
};
-(function() {
+(function () {
var functionNames = [
"reportRunnerStarting",
"reportRunnerResults",
"reportSuiteResults",
"reportSpecStarting",
"reportSpecResults",
- "log"
+ "log",
];
for (var i = 0; i < functionNames.length; i++) {
var functionName = functionNames[i];
- jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
- return function() {
+ 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]) {
@@ -1467,7 +1957,7 @@ jasmine.MultiReporter.prototype.addReporter = function(reporter) {
*
* @constructor
*/
-jasmine.NestedResults = function() {
+jasmine.NestedResults = function () {
/**
* The total count of results
*/
@@ -1495,7 +1985,7 @@ jasmine.NestedResults = function() {
*
* @param result
*/
-jasmine.NestedResults.prototype.rollupCounts = function(result) {
+jasmine.NestedResults.prototype.rollupCounts = function (result) {
this.totalCount += result.totalCount;
this.passedCount += result.passedCount;
this.failedCount += result.failedCount;
@@ -1505,14 +1995,14 @@ jasmine.NestedResults.prototype.rollupCounts = function(result) {
* Adds a log message.
* @param values Array of message parts which will be concatenated later.
*/
-jasmine.NestedResults.prototype.log = function(values) {
+jasmine.NestedResults.prototype.log = function (values) {
this.items_.push(new jasmine.MessageResult(values));
};
/**
* Getter for the results: message & results.
*/
-jasmine.NestedResults.prototype.getItems = function() {
+jasmine.NestedResults.prototype.getItems = function () {
return this.items_;
};
@@ -1520,8 +2010,8 @@ jasmine.NestedResults.prototype.getItems = function() {
* Adds a result, tracking counts (total, passed, & failed)
* @param {jasmine.ExpectationResult|jasmine.NestedResults} result
*/
-jasmine.NestedResults.prototype.addResult = function(result) {
- if (result.type != 'log') {
+jasmine.NestedResults.prototype.addResult = function (result) {
+ if (result.type != "log") {
if (result.items_) {
this.rollupCounts(result);
} else {
@@ -1539,13 +2029,13 @@ jasmine.NestedResults.prototype.addResult = function(result) {
/**
* @returns {Boolean} True if everything below passed
*/
-jasmine.NestedResults.prototype.passed = function() {
+jasmine.NestedResults.prototype.passed = function () {
return this.passedCount === this.totalCount;
};
/**
* Base class for pretty printing for expectation results.
*/
-jasmine.PrettyPrinter = function() {
+jasmine.PrettyPrinter = function () {
this.ppNestLevel_ = 0;
};
@@ -1554,36 +2044,36 @@ jasmine.PrettyPrinter = function() {
*
* @param value
*/
-jasmine.PrettyPrinter.prototype.format = function(value) {
- if (this.ppNestLevel_ > 40) {
- throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
- }
-
+jasmine.PrettyPrinter.prototype.format = function (value) {
this.ppNestLevel_++;
try {
if (value === jasmine.undefined) {
- this.emitScalar('undefined');
+ this.emitScalar("undefined");
} else if (value === null) {
- this.emitScalar('null');
+ this.emitScalar("null");
} else if (value === jasmine.getGlobal()) {
- this.emitScalar('');
- } else if (value instanceof jasmine.Matchers.Any) {
- this.emitScalar(value.toString());
- } else if (typeof value === 'string') {
+ this.emitScalar("");
+ } else if (value.jasmineToString) {
+ this.emitScalar(value.jasmineToString());
+ } 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 (typeof value === "function") {
+ this.emitScalar("Function");
+ } else if (typeof value.nodeType === "number") {
+ this.emitScalar("HTMLNode");
} else if (value instanceof Date) {
- this.emitScalar('Date(' + value + ')');
+ this.emitScalar("Date(" + value + ")");
} else if (value.__Jasmine_been_here_before__) {
- this.emitScalar('');
- } else if (jasmine.isArray_(value) || typeof value == 'object') {
+ this.emitScalar(
+ ""
+ );
+ } else if (jasmine.isArray_(value) || typeof value == "object") {
value.__Jasmine_been_here_before__ = true;
if (jasmine.isArray_(value)) {
this.emitArray(value);
@@ -1599,10 +2089,17 @@ jasmine.PrettyPrinter.prototype.format = function(value) {
}
};
-jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
+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);
+ if (!obj.hasOwnProperty(property)) continue;
+ if (property == "__Jasmine_been_here_before__") continue;
+ fn(
+ property,
+ obj.__lookupGetter__
+ ? obj.__lookupGetter__(property) !== jasmine.undefined &&
+ obj.__lookupGetter__(property) !== null
+ : false
+ );
}
};
@@ -1611,61 +2108,75 @@ jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
-jasmine.StringPrettyPrinter = function() {
+jasmine.StringPrettyPrinter = function () {
jasmine.PrettyPrinter.call(this);
- this.string = '';
+ this.string = "";
};
jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
-jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
+jasmine.StringPrettyPrinter.prototype.emitScalar = function (value) {
this.append(value);
};
-jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
+jasmine.StringPrettyPrinter.prototype.emitString = function (value) {
this.append("'" + value + "'");
};
-jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
- this.append('[ ');
+jasmine.StringPrettyPrinter.prototype.emitArray = function (array) {
+ if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
+ this.append("Array");
+ return;
+ }
+
+ this.append("[ ");
for (var i = 0; i < array.length; i++) {
if (i > 0) {
- this.append(', ');
+ this.append(", ");
}
this.format(array[i]);
}
- this.append(' ]');
+ this.append(" ]");
};
-jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
+jasmine.StringPrettyPrinter.prototype.emitObject = function (obj) {
+ if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
+ this.append("Object");
+ return;
+ }
+
var self = this;
- this.append('{ ');
+ this.append("{ ");
var first = true;
- this.iterateObject(obj, function(property, isGetter) {
+ this.iterateObject(obj, function (property, isGetter) {
if (first) {
first = false;
} else {
- self.append(', ');
+ self.append(", ");
}
self.append(property);
- self.append(' : ');
+ self.append(" : ");
if (isGetter) {
- self.append('');
+ self.append("");
} else {
self.format(obj[property]);
}
});
- this.append(' }');
+ this.append(" }");
};
-jasmine.StringPrettyPrinter.prototype.append = function(value) {
+jasmine.StringPrettyPrinter.prototype.append = function (value) {
this.string += value;
};
-jasmine.Queue = function(env) {
+jasmine.Queue = function (env) {
this.env = env;
+
+ // parallel to blocks. each true value in this array means the block will
+ // get executed even if we abort
+ this.ensured = [];
this.blocks = [];
this.running = false;
this.index = 0;
@@ -1673,39 +2184,57 @@ jasmine.Queue = function(env) {
this.abort = false;
};
-jasmine.Queue.prototype.addBefore = function(block) {
+jasmine.Queue.prototype.addBefore = function (block, ensure) {
+ if (ensure === jasmine.undefined) {
+ ensure = false;
+ }
+
this.blocks.unshift(block);
+ this.ensured.unshift(ensure);
};
-jasmine.Queue.prototype.add = function(block) {
+jasmine.Queue.prototype.add = function (block, ensure) {
+ if (ensure === jasmine.undefined) {
+ ensure = false;
+ }
+
this.blocks.push(block);
+ this.ensured.push(ensure);
};
-jasmine.Queue.prototype.insertNext = function(block) {
- this.blocks.splice((this.index + this.offset + 1), 0, block);
+jasmine.Queue.prototype.insertNext = function (block, ensure) {
+ if (ensure === jasmine.undefined) {
+ ensure = false;
+ }
+
+ this.ensured.splice(this.index + this.offset + 1, 0, ensure);
+ this.blocks.splice(this.index + this.offset + 1, 0, block);
this.offset++;
};
-jasmine.Queue.prototype.start = function(onComplete) {
+jasmine.Queue.prototype.start = function (onComplete) {
this.running = true;
this.onComplete = onComplete;
this.next_();
};
-jasmine.Queue.prototype.isRunning = function() {
+jasmine.Queue.prototype.isRunning = function () {
return this.running;
};
jasmine.Queue.LOOP_DONT_RECURSE = true;
-jasmine.Queue.prototype.next_ = function() {
+jasmine.Queue.prototype.next_ = function () {
var self = this;
var goAgain = true;
while (goAgain) {
goAgain = false;
-
- if (self.index < self.blocks.length && !this.abort) {
+
+ if (
+ self.index < self.blocks.length &&
+ !(this.abort && !this.ensured[self.index])
+ ) {
var calledSynchronously = true;
var completedSynchronously = false;
@@ -1723,9 +2252,12 @@ jasmine.Queue.prototype.next_ = function() {
self.index++;
var now = new Date().getTime();
- if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
+ if (
+ self.env.updateInterval &&
+ now - self.env.lastUpdate > self.env.updateInterval
+ ) {
self.env.lastUpdate = now;
- self.env.setTimeout(function() {
+ self.env.setTimeout(function () {
self.next_();
}, 0);
} else {
@@ -1742,7 +2274,6 @@ jasmine.Queue.prototype.next_ = function() {
if (completedSynchronously) {
onComplete();
}
-
} else {
self.running = false;
if (self.onComplete) {
@@ -1752,7 +2283,7 @@ jasmine.Queue.prototype.next_ = function() {
}
};
-jasmine.Queue.prototype.results = function() {
+jasmine.Queue.prototype.results = function () {
var results = new jasmine.NestedResults();
for (var i = 0; i < this.blocks.length; i++) {
if (this.blocks[i].results) {
@@ -1762,14 +2293,13 @@ jasmine.Queue.prototype.results = function() {
return results;
};
-
/**
* Runner
*
* @constructor
* @param {jasmine.Env} env
*/
-jasmine.Runner = function(env) {
+jasmine.Runner = function (env) {
var self = this;
self.env = env;
self.queue = new jasmine.Queue(env);
@@ -1778,7 +2308,7 @@ jasmine.Runner = function(env) {
self.suites_ = [];
};
-jasmine.Runner.prototype.execute = function() {
+jasmine.Runner.prototype.execute = function () {
var self = this;
if (self.env.reporter.reportRunnerStarting) {
self.env.reporter.reportRunnerStarting(this);
@@ -1788,26 +2318,25 @@ jasmine.Runner.prototype.execute = function() {
});
};
-jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
- beforeEachFunction.typeName = 'beforeEach';
- this.before_.splice(0,0,beforeEachFunction);
+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.afterEach = function (afterEachFunction) {
+ afterEachFunction.typeName = "afterEach";
+ this.after_.splice(0, 0, afterEachFunction);
};
-
-jasmine.Runner.prototype.finishCallback = function() {
+jasmine.Runner.prototype.finishCallback = function () {
this.env.reporter.reportRunnerResults(this);
};
-jasmine.Runner.prototype.addSuite = function(suite) {
+jasmine.Runner.prototype.addSuite = function (suite) {
this.suites_.push(suite);
};
-jasmine.Runner.prototype.add = function(block) {
+jasmine.Runner.prototype.add = function (block) {
if (block instanceof jasmine.Suite) {
this.addSuite(block);
}
@@ -1823,11 +2352,11 @@ jasmine.Runner.prototype.specs = function () {
return specs;
};
-jasmine.Runner.prototype.suites = function() {
+jasmine.Runner.prototype.suites = function () {
return this.suites_;
};
-jasmine.Runner.prototype.topLevelSuites = function() {
+jasmine.Runner.prototype.topLevelSuites = function () {
var topLevelSuites = [];
for (var i = 0; i < this.suites_.length; i++) {
if (!this.suites_[i].parentSuite) {
@@ -1837,7 +2366,7 @@ jasmine.Runner.prototype.topLevelSuites = function() {
return topLevelSuites;
};
-jasmine.Runner.prototype.results = function() {
+jasmine.Runner.prototype.results = function () {
return this.queue.results();
};
/**
@@ -1848,12 +2377,12 @@ jasmine.Runner.prototype.results = function() {
* @param {jasmine.Suite} suite
* @param {String} description
*/
-jasmine.Spec = function(env, suite, description) {
+jasmine.Spec = function (env, suite, description) {
if (!env) {
- throw new Error('jasmine.Env() required');
+ throw new Error("jasmine.Env() required");
}
if (!suite) {
- throw new Error('jasmine.Suite() required');
+ throw new Error("jasmine.Suite() required");
}
var spec = this;
spec.id = env.nextSpecId ? env.nextSpecId() : null;
@@ -1870,12 +2399,11 @@ jasmine.Spec = function(env, suite, description) {
spec.matchersClass = null;
};
-jasmine.Spec.prototype.getFullName = function() {
- return this.suite.getFullName() + ' ' + this.description + '.';
+jasmine.Spec.prototype.getFullName = function () {
+ return this.suite.getFullName() + " " + this.description + ".";
};
-
-jasmine.Spec.prototype.results = function() {
+jasmine.Spec.prototype.results = function () {
return this.results_;
};
@@ -1884,7 +2412,7 @@ jasmine.Spec.prototype.results = function() {
*
* Be careful not to leave calls to jasmine.log
in production code.
*/
-jasmine.Spec.prototype.log = function() {
+jasmine.Spec.prototype.log = function () {
return this.results_.log(arguments);
};
@@ -1905,11 +2433,11 @@ jasmine.Spec.prototype.addToQueue = function (block) {
/**
* @param {jasmine.ExpectationResult} result
*/
-jasmine.Spec.prototype.addMatcherResult = function(result) {
+jasmine.Spec.prototype.addMatcherResult = function (result) {
this.results_.addResult(result);
};
-jasmine.Spec.prototype.expect = function(actual) {
+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;
@@ -1921,7 +2449,7 @@ jasmine.Spec.prototype.expect = function(actual) {
* @deprecated Use waitsFor() instead
* @param {Number} timeout milliseconds to wait
*/
-jasmine.Spec.prototype.waits = function(timeout) {
+jasmine.Spec.prototype.waits = function (timeout) {
var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
this.addToQueue(waitsFunc);
return this;
@@ -1934,7 +2462,11 @@ jasmine.Spec.prototype.waits = function(timeout) {
* @param {String} optional_timeoutMessage
* @param {Number} optional_timeout
*/
-jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
+jasmine.Spec.prototype.waitsFor = function (
+ latchFunction,
+ optional_timeoutMessage,
+ optional_timeout
+) {
var latchFunction_ = null;
var optional_timeoutMessage_ = null;
var optional_timeout_ = null;
@@ -1942,19 +2474,25 @@ jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessag
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
switch (typeof arg) {
- case 'function':
+ case "function":
latchFunction_ = arg;
break;
- case 'string':
+ case "string":
optional_timeoutMessage_ = arg;
break;
- case 'number':
+ case "number":
optional_timeout_ = arg;
break;
}
}
- var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
+ var waitsForFunc = new jasmine.WaitsForBlock(
+ this.env,
+ optional_timeout_,
+ latchFunction_,
+ optional_timeoutMessage_,
+ this
+ );
this.addToQueue(waitsForFunc);
return this;
};
@@ -1962,18 +2500,19 @@ jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessag
jasmine.Spec.prototype.fail = function (e) {
var expectationResult = new jasmine.ExpectationResult({
passed: false,
- message: e ? jasmine.util.formatException(e) : 'Exception'
+ message: e ? jasmine.util.formatException(e) : "Exception",
+ trace: { stack: e.stack },
});
this.results_.addResult(expectationResult);
};
-jasmine.Spec.prototype.getMatchersClass_ = function() {
+jasmine.Spec.prototype.getMatchersClass_ = function () {
return this.matchersClass || this.env.matchersClass;
};
-jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
+jasmine.Spec.prototype.addMatchers = function (matchersPrototype) {
var parent = this.getMatchersClass_();
- var newMatchersClass = function() {
+ var newMatchersClass = function () {
parent.apply(this, arguments);
};
jasmine.util.inherit(newMatchersClass, parent);
@@ -1981,11 +2520,11 @@ jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
this.matchersClass = newMatchersClass;
};
-jasmine.Spec.prototype.finishCallback = function() {
+jasmine.Spec.prototype.finishCallback = function () {
this.env.reporter.reportSpecResults(this);
};
-jasmine.Spec.prototype.finish = function(onComplete) {
+jasmine.Spec.prototype.finish = function (onComplete) {
this.removeAllSpies();
this.finishCallback();
if (onComplete) {
@@ -1993,15 +2532,15 @@ jasmine.Spec.prototype.finish = function(onComplete) {
}
};
-jasmine.Spec.prototype.after = function(doAfter) {
+jasmine.Spec.prototype.after = function (doAfter) {
if (this.queue.isRunning()) {
- this.queue.add(new jasmine.Block(this.env, doAfter, this));
+ this.queue.add(new jasmine.Block(this.env, doAfter, this), true);
} else {
this.afterCallbacks.unshift(doAfter);
}
};
-jasmine.Spec.prototype.execute = function(onComplete) {
+jasmine.Spec.prototype.execute = function (onComplete) {
var spec = this;
if (!spec.env.specFilter(spec)) {
spec.results_.skipped = true;
@@ -2020,7 +2559,7 @@ jasmine.Spec.prototype.execute = function(onComplete) {
});
};
-jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
+jasmine.Spec.prototype.addBeforesAndAftersToQueue = function () {
var runner = this.env.currentRunner();
var i;
@@ -2033,33 +2572,40 @@ jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
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));
+ this.queue.add(
+ new jasmine.Block(this.env, this.afterCallbacks[i], this),
+ true
+ );
}
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));
+ this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true);
}
}
for (i = 0; i < runner.after_.length; i++) {
- this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
+ this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true);
}
};
-jasmine.Spec.prototype.explodes = function() {
- throw 'explodes function should not have been called';
+jasmine.Spec.prototype.explodes = function () {
+ throw "explodes function should not have been called";
};
-jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
+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';
+ throw methodName + "() method does not exist";
}
if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
- throw new Error(methodName + ' has already been spied upon');
+ throw new Error(methodName + " has already been spied upon");
}
var spyObj = jasmine.createSpy(methodName);
@@ -2074,7 +2620,7 @@ jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist
return spyObj;
};
-jasmine.Spec.prototype.removeAllSpies = function() {
+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;
@@ -2091,7 +2637,7 @@ jasmine.Spec.prototype.removeAllSpies = function() {
* @param {Function} specDefinitions
* @param {jasmine.Suite} parentSuite
*/
-jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
+jasmine.Suite = function (env, description, specDefinitions, parentSuite) {
var self = this;
self.id = env.nextSuiteId ? env.nextSuiteId() : null;
self.description = description;
@@ -2105,37 +2651,41 @@ jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
self.specs_ = [];
};
-jasmine.Suite.prototype.getFullName = function() {
+jasmine.Suite.prototype.getFullName = function () {
var fullName = this.description;
- for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
- fullName = parentSuite.description + ' ' + fullName;
+ for (
+ var parentSuite = this.parentSuite;
+ parentSuite;
+ parentSuite = parentSuite.parentSuite
+ ) {
+ fullName = parentSuite.description + " " + fullName;
}
return fullName;
};
-jasmine.Suite.prototype.finish = function(onComplete) {
+jasmine.Suite.prototype.finish = function (onComplete) {
this.env.reporter.reportSuiteResults(this);
this.finished = true;
- if (typeof(onComplete) == 'function') {
+ if (typeof onComplete == "function") {
onComplete();
}
};
-jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
- beforeEachFunction.typeName = 'beforeEach';
+jasmine.Suite.prototype.beforeEach = function (beforeEachFunction) {
+ beforeEachFunction.typeName = "beforeEach";
this.before_.unshift(beforeEachFunction);
};
-jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
- afterEachFunction.typeName = 'afterEach';
+jasmine.Suite.prototype.afterEach = function (afterEachFunction) {
+ afterEachFunction.typeName = "afterEach";
this.after_.unshift(afterEachFunction);
};
-jasmine.Suite.prototype.results = function() {
+jasmine.Suite.prototype.results = function () {
return this.queue.results();
};
-jasmine.Suite.prototype.add = function(suiteOrSpec) {
+jasmine.Suite.prototype.add = function (suiteOrSpec) {
this.children_.push(suiteOrSpec);
if (suiteOrSpec instanceof jasmine.Suite) {
this.suites_.push(suiteOrSpec);
@@ -2146,25 +2696,25 @@ jasmine.Suite.prototype.add = function(suiteOrSpec) {
this.queue.add(suiteOrSpec);
};
-jasmine.Suite.prototype.specs = function() {
+jasmine.Suite.prototype.specs = function () {
return this.specs_;
};
-jasmine.Suite.prototype.suites = function() {
+jasmine.Suite.prototype.suites = function () {
return this.suites_;
};
-jasmine.Suite.prototype.children = function() {
+jasmine.Suite.prototype.children = function () {
return this.children_;
};
-jasmine.Suite.prototype.execute = function(onComplete) {
+jasmine.Suite.prototype.execute = function (onComplete) {
var self = this;
this.queue.start(function () {
self.finish(onComplete);
});
};
-jasmine.WaitsBlock = function(env, timeout, spec) {
+jasmine.WaitsBlock = function (env, timeout, spec) {
this.timeout = timeout;
jasmine.Block.call(this, env, null, spec);
};
@@ -2172,7 +2722,9 @@ jasmine.WaitsBlock = function(env, timeout, spec) {
jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
jasmine.WaitsBlock.prototype.execute = function (onComplete) {
- this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
+ if (jasmine.VERBOSE) {
+ this.env.reporter.log(">> Jasmine waiting for " + this.timeout + " ms...");
+ }
this.env.setTimeout(function () {
onComplete();
}, this.timeout);
@@ -2188,7 +2740,7 @@ jasmine.WaitsBlock.prototype.execute = function (onComplete) {
* @param {String} message The message to display if the desired condition hasn't been met within the given time period.
* @param {jasmine.Spec} spec The Jasmine spec.
*/
-jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
+jasmine.WaitsForBlock = function (env, timeout, latchFunction, message, spec) {
this.timeout = timeout || env.defaultTimeoutInterval;
this.latchFunction = latchFunction;
this.message = message;
@@ -2199,8 +2751,12 @@ jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
-jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
- this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
+jasmine.WaitsForBlock.prototype.execute = function (onComplete) {
+ if (jasmine.VERBOSE) {
+ this.env.reporter.log(
+ ">> Jasmine waiting for " + (this.message || "something to happen")
+ );
+ }
var latchFunctionResult;
try {
latchFunctionResult = this.latchFunction.apply(this.spec);
@@ -2213,209 +2769,31 @@ jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
if (latchFunctionResult) {
onComplete();
} else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
- var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
+ var message =
+ "timed out after " +
+ this.timeout +
+ " msec waiting for " +
+ (this.message || "something to happen");
this.spec.fail({
- name: 'timeout',
- message: message
+ name: "timeout",
+ message: message,
});
this.abort = true;
onComplete();
} else {
- this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
+ this.totalTimeSpentWaitingForLatch +=
+ jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
var self = this;
- this.env.setTimeout(function() {
+ this.env.setTimeout(function () {
self.execute(onComplete);
}, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
}
};
-// 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);
- }
-};
-
-jasmine.version_= {
- "major": 1,
- "minor": 0,
- "build": "0.rc1",
- "revision": 1282853377
+jasmine.version_ = {
+ major: 1,
+ minor: 3,
+ build: 1,
+ revision: 1354556913,
};
diff --git a/lib/jasmine/jskoans-jasmine-html.js b/lib/jasmine/jskoans-jasmine-html.js
index e43763e2b..d319130c1 100644
--- a/lib/jasmine/jskoans-jasmine-html.js
+++ b/lib/jasmine/jskoans-jasmine-html.js
@@ -1,245 +1,306 @@
-JsKoansReporter = function(doc) {
- this.document = doc || document;
- this.suiteDivs = {};
- this.failedSpecs = 0;
-
- this.noOfSubjects = 0;
- this.failedSubjects = 0;
-};
-
-JsKoansReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
- var el = document.createElement(type);
+class JsKoansReporter {
+ constructor(doc = document) {
+ this.document = doc;
+ this.suiteDivs = {};
+ this.failedSpecs = 0;
+ this.noOfSubjects = 0;
+ this.failedSubjects = 0;
+ }
- for (var i = 2; i < arguments.length; i++) {
- var child = arguments[i];
+ createDom(type, attrs, ...children) {
+ const element = document.createElement(type);
- if (typeof child === 'string') {
- el.appendChild(document.createTextNode(child));
- } else {
- if (child) { el.appendChild(child); }
+ for (const child of children) {
+ if (typeof child === "string")
+ element.appendChild(document.createTextNode(child));
+ else if (child) element.appendChild(child);
}
- }
- for (var attr in attrs) {
- if (attr == "className") {
- el[attr] = attrs[attr];
- } else {
- el.setAttribute(attr, attrs[attr]);
+ for (const attr in attrs) {
+ if (attr == "className") {
+ element[attr] = attrs[attr];
+ } else {
+ element.setAttribute(attr, attrs[attr]);
+ }
}
- }
- return el;
-};
+ return element;
+ }
-JsKoansReporter.prototype.reportRunnerStarting = function(runner) {
- this.outerDiv = this.createDom('div', { className: 'jasmine_reporter show-passed' },
- this.createDom('h1', { }, "Javascript Koans"),
- this.runnerDiv = this.createDom('div', { className: 'runner running' },
- this.runnerMessageSpan = this.createDom('span', { classname: 'running' }, "Contemplating naval..."),
- this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
+ reportRunnerStarting(runner) {
+ this.outerDiv = this.createDom(
+ "div",
+ { className: "jasmine_reporter show-passed" },
+ this.createDom("h1", {}, "Javascript Koans"),
+ (this.runnerDiv = this.createDom(
+ "div",
+ { className: "runner running" },
+ (this.runnerMessageSpan = this.createDom(
+ "span",
+ { classname: "running" },
+ "Contemplating naval..."
+ )),
+ (this.finishedAtSpan = this.createDom("span", {
+ className: "finished-at",
+ }))
+ ))
+ );
+
+ this.document.body.appendChild(this.outerDiv);
+
+ const suites = runner.suites();
+ for (const suite of suites) {
+ const suiteDiv = this.createDom(
+ "div",
+ { className: "suite" },
+ this.createDom(
+ "a",
+ {
+ className: "description",
+ href: `?spec=${encodeURIComponent(suite.getFullName())}`,
+ },
+ this.getSuiteDescription(suite)
+ )
);
-
- 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: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) },
- this.getSuiteDescription(suite)));
- this.suiteDivs[suite.id] = suiteDiv;
- var parentDiv = this.outerDiv;
- if (suite.parentSuite) {
- parentDiv = this.suiteDivs[suite.parentSuite.id];
+ this.suiteDivs[suite.id] = suiteDiv;
+ const parentDiv = suite.parentChild
+ ? this.suiteDivs[suite.parentSuite.id]
+ : this.outerDiv;
+ parentDiv.appendChild(suiteDiv);
}
- parentDiv.appendChild(suiteDiv);
- }
- this.footerDiv = this.createDom('div', { className: 'banner' },
- this.createDom('div', { className: 'logo' },
+ this.footerDiv = this.createDom(
+ "div",
+ { className: "banner" },
+ this.createDom(
+ "div",
+ { className: "logo" },
"Test runner: Jasmine",
- this.createDom('span', { className: 'version' }, runner.env.versionString()))
- );
+ this.createDom(
+ "span",
+ { className: "version" },
+ runner.env.versionString()
+ )
+ )
+ );
- this.outerDiv.appendChild(this.footerDiv);
-
- this.startedAt = new Date();
-};
-
-JsKoansReporter.prototype.reportRunnerResults = function(runner) {
- var results = runner.results();
- var className = "progress";
- 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++;
- }
- }
+ this.outerDiv.appendChild(this.footerDiv);
- var resultMessage;
- if (this.failedSpecs === 0) {
- status = 'passed';
- resultMessage = "Success!";
- } else {
- status = 'failed';
- resultMessage = "You have not yet reached success...";
+ this.startedAt = new Date();
}
- var suitesCount = runner.suites().length;
- var specsCount = runner.specs().length;
- var showPassed;
- var showAllFailed;
-
- var progress = this.createDom('div', {},
- this.createDom('div', { className: 'success-' + status }, resultMessage),
- this.createDom('div', { className: 'completion' },
- this.createDom('div', {},
- this.createDom('span', { className: 'key' }, "Subjects covered: "),
- this.createDom('span', { className: 'value' }, this.noOfSubjects - this.failedSubjects + "/" + this.noOfSubjects)
+ reportRunnerResults(runner) {
+ const className = "progress";
+ this.runnerDiv.setAttribute("class", className);
+
+ const specs = runner.specs();
+ let specCount = 0;
+ for (const spec of specs) {
+ if (this.specFilter(spec)) specCount++;
+ }
+
+ const status = this.failedSpecs === 0 ? "passed" : "failed";
+ const resultMessage =
+ this.failedSpecs === 0
+ ? "Success!"
+ : "You have not yet reached success...";
+
+ const specsCount = runner.specs().length;
+ let showPassed;
+ let showAllFailed;
+
+ const progress = this.createDom(
+ "div",
+ {},
+ this.createDom("div", { className: `success-${status}` }, resultMessage),
+ this.createDom(
+ "div",
+ { className: "completion" },
+ this.createDom(
+ "div",
+ {},
+ this.createDom("span", { className: "key" }, "Subjects covered: "),
+ this.createDom(
+ "span",
+ { className: "value" },
+ `${this.noOfSubjects - this.failedSubjects}/${this.noOfSubjects}`
+ )
+ ),
+ this.createDom(
+ "div",
+ {},
+ this.createDom("span", { className: "key" }, "Koans learned: "),
+ this.createDom(
+ "span",
+ { className: "value" },
+ `${specsCount - this.failedSpecs}/${runner.specs().length}`
+ )
+ ),
+ this.createDom(
+ "div",
+ { className: "options" },
+ this.createDom(
+ "label",
+ { for: "__jsKoans_showPassed__" },
+ " Show passed koans"
),
- this.createDom('div', {},
- this.createDom('span', { className: 'key' }, "Koans learned: "),
- this.createDom('span', { className: 'value' }, specsCount - this.failedSpecs + "/" + runner.specs().length)
+ (showPassed = this.createDom("input", {
+ id: "__jsKoans_showPassed__",
+ type: "checkbox",
+ checked: "",
+ })),
+ this.createDom(
+ "label",
+ { for: "__jsKoans_showAllFailed__" },
+ " Look ahead"
),
- this.createDom('div', { className: 'options' },
- this.createDom('label', { "for": "__jsKoans_showPassed__" }, " Show passed koans"),
- showPassed = this.createDom('input', { id: "__jsKoans_showPassed__", type: 'checkbox', checked: '' }),
- this.createDom('label', { "for": "__jsKoans_showAllFailed__" }, " Look ahead"),
- showAllFailed = this.createDom('input', { id: "__jsKoans_showAllFailed__", type: 'checkbox' })
- )
- )
- );
- this.runnerMessageSpan.replaceChild(this.createDom('div', { className: 'description', href: '?'}, progress), this.runnerMessageSpan.firstChild);
-
- 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/, '');
- }
- };
- showAllFailed.onchange = function(evt) {
- if (evt.target.checked) {
- self.outerDiv.className += ' show-skipped';
- } else {
- self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
- }
- };
-};
-
-JsKoansReporter.prototype.reportSuiteResults = function(suite) {
- var results = suite.results();
- var status = results.passed() ? 'passed' : 'failed';
- if (results.totalCount == 0 || this.failedSubjects > 0) {
- status += '-skipped';
+ (showAllFailed = this.createDom("input", {
+ id: "__jsKoans_showAllFailed__",
+ type: "checkbox",
+ }))
+ )
+ )
+ );
+ this.runnerMessageSpan.replaceChild(
+ this.createDom("div", { className: "description", href: "?" }, progress),
+ this.runnerMessageSpan.firstChild
+ );
+
+ showPassed.onchange = (evt) => {
+ if (evt.target.checked) {
+ this.outerDiv.className += " show-passed";
+ } else {
+ this.outerDiv.className = this.outerDiv.className.replace(
+ / show-passed/,
+ ""
+ );
+ }
+ };
+ showAllFailed.onchange = (evt) => {
+ if (evt.target.checked) {
+ this.outerDiv.className += " show-skipped";
+ } else {
+ this.outerDiv.className = this.outerDiv.className.replace(
+ / show-skipped/,
+ ""
+ );
+ }
+ };
}
- if (suite.parentSuite == null) {
- this.noOfSubjects +=1;
- if (this.failedSpecs > 0) {
- this.failedSubjects += 1;
+ reportSuiteResults(suite) {
+ const results = suite.results();
+ let status = results.passed() ? "passed" : "failed";
+ if (results.totalCount == 0 || this.failedSubjects > 0) {
+ status += "-skipped";
}
- }
-
- this.suiteDivs[suite.id].className += " " + status;
-};
-JsKoansReporter.prototype.reportSpecStarting = function(spec) {
-};
-
-JsKoansReporter.prototype.reportSpecResults = function(spec) {
- var results = spec.results();
- var status = results.passed() ? 'passed' : 'failed';
- var skipStatus = status;
-
- if (results.skipped || this.failedSpecs > 0) {
- skipStatus += '-skipped';
- }
-
- var description;
- if ( !results.passed() ) {
- this.failedSpecs += 1;
+ if (suite.parentSuite == null) {
+ this.noOfSubjects += 1;
+ if (this.failedSpecs > 0) this.failedSubjects += 1;
+ }
- description = "It " + spec.description + ". You should continue thinking about this koan."
- } else {
- description = "You understand that it " + spec.description;
+ this.suiteDivs[suite.id].className += ` ${status}`;
}
- var specDiv = this.createDom('div', { className: 'spec ' + skipStatus },
- this.createDom('a', { className: 'run_spec_' + status, href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "meditate again"),
- this.createDom('a', {
- className: 'description',
- href: '?spec=' + encodeURIComponent(spec.getFullName()),
- title: spec.getFullName()
- }, description));
+ reportSpecStarting() {}
- var resultItems = results.getItems();
- var messagesDiv = this.createDom('div', { className: 'messages'});
+ reportSpecResults(spec) {
+ const results = spec.results();
+ const status = results.passed() ? "passed" : "failed";
+ let skipStatus = status;
- for (var i = 0; i < resultItems.length; i++) {
- var result = resultItems[i];
+ if (results.skipped || this.failedSpecs > 0) {
+ skipStatus += "-skipped";
+ }
- if (result.type == 'expect' && result.passed && !result.passed()) {
- messagesDiv.appendChild(
- this.createDom('div', { className: 'errorMessage' }, result.message)
- );
- messagesDiv.appendChild(
- this.createDom('div', { className: 'description' }, "Please rethink the following code:")
+ const description = results.passed()
+ ? `You understand that it ${spec.description}.`
+ : `It ${spec.description}. You should continue thinking about this koan.`;
+ if (!results.passed()) this.failedSpecs += 1;
+
+ const specDiv = this.createDom(
+ "div",
+ { className: "spec " + skipStatus },
+ this.createDom(
+ "a",
+ {
+ className: "run_spec_" + status,
+ href: `?spec=${encodeURIComponent(spec.getFullName())}`,
+ },
+ "meditate again"
+ ),
+ this.createDom(
+ "a",
+ {
+ className: "description",
+ href: `?spec=${encodeURIComponent(spec.getFullName())}`,
+ title: spec.getFullName(),
+ },
+ description
+ )
+ );
+
+ const resultItems = results.getItems();
+ const messagesDiv = this.createDom("div", { className: "messages" });
+
+ for (const result of resultItems) {
+ if (result.type == "expect" && result.passed && !result.passed()) {
+ messagesDiv.appendChild(
+ this.createDom("div", { className: "errorMessage" }, result.message)
+ );
+ messagesDiv.appendChild(
+ this.createDom(
+ "div",
+ { className: "description" },
+ "Please rethink the following code:"
+ )
+ );
+
+ if (result.trace.stack) {
+ const lines = result.trace.stack.split("\n");
+ const stack = [
+ lines[0],
+ ...lines.slice(1).filter((line) => line.includes("/koans/")),
+ ].join("\n");
+ messagesDiv.appendChild(
+ this.createDom("div", { className: "stackTrace" }, stack.trim())
);
-
- if (result.trace.stack) {
- var lines = result.trace.stack.split('\n');
- var stack = lines[0];
- for (var i = 1; i < lines.length; i++) {
- if (lines[i].search('/koans/') != -1) {
- stack += '\n' + lines[i]
- }
}
- messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, stack.trim()));
- }
- break;
+ break;
+ }
}
+ if (messagesDiv.childNodes.length > 0) specDiv.appendChild(messagesDiv);
+
+ this.suiteDivs[spec.suite.id].appendChild(specDiv);
}
- if (messagesDiv.childNodes.length > 0) {
- specDiv.appendChild(messagesDiv);
+
+ log() {
+ const { console } = jasmine.getGlobal();
+ if (console && console.log) console.log.apply(console, arguments);
}
- this.suiteDivs[spec.suite.id].appendChild(specDiv);
-
-};
-
-JsKoansReporter.prototype.log = function() {
- var console = jasmine.getGlobal().console;
- if (console && console.log) console.log.apply(console, arguments);
-};
-
-JsKoansReporter.prototype.getLocation = function() {
- return this.document.location;
-};
-
-JsKoansReporter.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]);
+ getLocation() {
+ return this.document.location;
}
- if (!paramMap["spec"]) return true;
- return spec.getFullName().indexOf(paramMap["spec"]) == 0;
-};
+ specFilter(spec) {
+ const paramMap = {};
+ const params = this.getLocation().search.substring(1).split("&");
+ for (const param of params) {
+ const [key, value] = param.split("=");
+ paramMap[decodeURIComponent(key)] = decodeURIComponent(value);
+ }
-JsKoansReporter.prototype.getSuiteDescription = function(suite) {
- if (null === suite.parentSuite) {
- return "Thinking " + suite.description;
- } else {
- return "Considering " + suite.description;
+ return paramMap["spec"]
+ ? spec.getFullName().indexOf(paramMap["spec"]) === 0
+ : true;
}
-};
+ getSuiteDescription(suite) {
+ return `${suite.parentSuite === null ? "Thinking" : "Considering"} ${
+ suite.description
+ }`;
+ }
+}
diff --git a/lib/jasmine/jskoans-jasmine.css b/lib/jasmine/jskoans-jasmine.css
index 1c71fb1de..609f28c2c 100644
--- a/lib/jasmine/jskoans-jasmine.css
+++ b/lib/jasmine/jskoans-jasmine.css
@@ -1,5 +1,6 @@
body {
- font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
+ font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial",
+ sans-serif;
}
h1 {
@@ -8,18 +9,21 @@ h1 {
color: #78f;
}
-.jasmine_reporter a:visited, .jasmine_reporter a {
- color: #303;
+.jasmine_reporter a:visited,
+.jasmine_reporter a {
+ color: #303;
}
-.jasmine_reporter a:hover, .jasmine_reporter a:active {
- color: blue;
+.jasmine_reporter a:hover,
+.jasmine_reporter a:active {
+ color: blue;
}
-.run_spec_failed, .run_spec_skipped {
- float:right;
+.run_spec_failed,
+.run_spec_skipped {
+ float: right;
padding-right: 5px;
- font-size: .8em;
+ font-size: 0.8em;
text-decoration: none;
}
@@ -61,14 +65,16 @@ h1 {
}
.suite .suite {
- margin: 5px;
+ margin: 5px;
}
-.suite.passed, .suite.passed-skipped {
+.suite.passed,
+.suite.passed-skipped {
background-color: #dfd;
}
-.suite.failed, .suite.failed-skipped {
+.suite.failed,
+.suite.failed-skipped {
background-color: #fdd;
}
@@ -78,17 +84,22 @@ h1 {
clear: both;
}
-.spec.failed, .spec.passed, .spec.passed-skipped, .spec.failed-skipped {
+.spec.failed,
+.spec.passed,
+.spec.passed-skipped,
+.spec.failed-skipped {
padding-bottom: 5px;
border: 1px solid gray;
}
-.spec.failed, .spec.failed-skipped {
+.spec.failed,
+.spec.failed-skipped {
background-color: #fbb;
border-color: red;
}
-.spec.passed, .spec.passed-skipped {
+.spec.passed,
+.spec.passed-skipped {
background-color: #bfb;
border-color: green;
}
@@ -98,10 +109,11 @@ h1 {
}
.errorMessage {
- font-family: "Menlo", "Monaco", "Andale Mono", "Courier New", "Courier", sans-serif;
+ font-family: "Menlo", "Monaco", "Andale Mono", "Courier New", "Courier",
+ sans-serif;
color: #055;
white-space: pre;
- padding: .2em 1em;
+ padding: 0.2em 1em;
margin-left: 10px;
margin-right: 5px;
margin-bottom: 10px;
@@ -122,9 +134,10 @@ h1 {
display: block;
}
-.passed-skipped, .failed-skipped {
- display: none;
-}
+.passed-skipped,
+.failed-skipped {
+ display: none;
+}
.resultMessage span.result {
display: block;
@@ -138,7 +151,7 @@ h1 {
.stackTrace {
white-space: pre;
- font-size: .8em;
+ font-size: 0.8em;
margin-left: 10px;
margin-right: 5px;
max-height: 5em;
@@ -151,7 +164,7 @@ h1 {
.finished-at {
padding-left: 1em;
- font-size: .6em;
+ font-size: 0.6em;
}
.show-skipped .passed-skipped {
@@ -170,7 +183,7 @@ h1 {
}
#jasmine_content {
- position:fixed;
+ position: fixed;
right: 100%;
}
@@ -185,7 +198,7 @@ h1 {
}
.completion {
- font-size: .9em;
+ font-size: 0.9em;
padding-top: 10px;
}
diff --git a/lib/jasmine/runner_specs/TestJSKoansRunner.html b/lib/jasmine/runner_specs/TestJSKoansRunner.html
index 06885ad61..46b4d0f98 100644
--- a/lib/jasmine/runner_specs/TestJSKoansRunner.html
+++ b/lib/jasmine/runner_specs/TestJSKoansRunner.html
@@ -1,24 +1,21 @@
-
+
-
- Jasmine Test Runner
-
-
-
+
+ Jasmine Test Runner
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/lib/jasmine/runner_specs/suites/KoansRunnerSpec.js b/lib/jasmine/runner_specs/suites/KoansRunnerSpec.js
index 9a838c3ca..bc33a7e9b 100644
--- a/lib/jasmine/runner_specs/suites/KoansRunnerSpec.js
+++ b/lib/jasmine/runner_specs/suites/KoansRunnerSpec.js
@@ -1,10 +1,10 @@
-describe("KoansRunner", function() {
- var env;
- var reporter;
- var body;
- var fakeDocument;
+describe("KoansRunner", () => {
+ let env;
+ let reporter;
+ let body;
+ let fakeDocument;
- beforeEach(function() {
+ beforeEach(() => {
env = new jasmine.Env();
env.updateInterval = 0;
@@ -15,166 +15,177 @@ describe("KoansRunner", function() {
function fakeSpec(name) {
return {
- getFullName: function() {
+ getFullName() {
return name;
- }
+ },
};
}
function fakeSuite(desc) {
return {
parentSuite: null,
- description: desc
+ description: desc,
};
}
function findElements(divs, withClass) {
- var els = [];
- for (var i = 0; i < divs.length; i++) {
- if (divs[i].className == withClass) els.push(divs[i]);
+ const elements = [];
+ for (const div of divs) {
+ if (div.className == withClass) elements.push(div);
}
- return els;
+ return elements;
}
function findElement(divs, withClass) {
- var els = findElements(divs, withClass);
- if (els.length > 0) return els[0];
+ const elements = findElements(divs, withClass);
+ if (elements.length > 0) return elements[0];
throw new Error("couldn't find div with class " + withClass);
}
- it("should run only specs beginning with spec parameter", function() {
+ it("should run only specs beginning with spec parameter", () => {
fakeDocument.location.search = "?spec=run%20this";
expect(reporter.specFilter(fakeSpec("run this"))).toBeTruthy();
expect(reporter.specFilter(fakeSpec("not the right spec"))).toBeFalsy();
expect(reporter.specFilter(fakeSpec("not run this"))).toBeFalsy();
});
- it("should display empty divs for every suite when the runner is starting", function() {
+ it("should display empty divs for every suite when the runner is starting", () => {
reporter.reportRunnerStarting({
env: env,
- suites: function() {
- return [ new jasmine.Suite({}, "suite 1", null, null) ];
- }
+ suites() {
+ return [new jasmine.Suite({}, "suite 1", null, null)];
+ },
});
- var divs = findElements(body.getElementsByTagName("div"), "suite");
+ const divs = findElements(body.getElementsByTagName("div"), "suite");
expect(divs.length).toEqual(1);
expect(divs[0].innerHTML).toContain("suite 1");
});
- describe('Matcher reporting', function () {
- var getErrorMessageDiv = function (body) {
- var divs = body.getElementsByTagName("div");
- for (var i = 0; i < divs.length; i++) {
- if (divs[i].className.match(/errorMessage/)) {
- return divs[i];
+ describe("Matcher reporting", () => {
+ const getErrorMessageDiv = function (body) {
+ const divs = body.getElementsByTagName("div");
+ for (const div of divs) {
+ if (div.className.match(/errorMessage/)) {
+ return div;
}
}
};
- var runner, spec, fakeTimer;
- beforeEach(function () {
+ let runner;
+ let spec;
+ let fakeTimer;
+ beforeEach(() => {
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');
+ const suite = new jasmine.Suite(env, "some suite");
runner.add(suite);
- spec = new jasmine.Spec(env, suite, 'some spec');
+ spec = new jasmine.Spec(env, suite, "some spec");
suite.add(spec);
fakeDocument.location.search = "?";
env.addReporter(reporter);
});
- describe('toContain', function () {
- it('should show actual and expected', function () {
+ describe("toContain", () => {
+ it("should show actual and expected", () => {
spec.runs(function () {
- this.expect('foo').toContain('bar');
+ this.expect("foo").toContain("bar");
});
runner.execute();
fakeTimer.tick(0);
- var resultEl = getErrorMessageDiv(body);
+ const resultEl = getErrorMessageDiv(body);
expect(resultEl.innerHTML).toMatch(/foo/);
expect(resultEl.innerHTML).toMatch(/bar/);
});
});
});
+ describe("failure messages (integration)", () => {
+ let spec;
+ let results;
+ let expectationResult;
- describe("failure messages (integration)", function () {
- var spec, results, expectationResult;
-
- beforeEach(function() {
+ beforeEach(() => {
results = {
- passed: function() {
+ passed() {
return false;
},
- getItems: function() {
- }};
+ getItems() {},
+ };
- var suite1 = new jasmine.Suite(env, "suite 1", null, null);
+ const suite1 = new jasmine.Suite(env, "suite 1", null, null);
spec = {
suite: suite1,
- getFullName: function() {
+ getFullName() {
return "foo";
},
- results: function() {
+ results() {
return results;
- }
+ },
};
reporter.reportRunnerStarting({
env: env,
- suites: function() {
- return [ suite1 ];
- }
+ suites() {
+ return [suite1];
+ },
});
});
- it("should add the failure message to the DOM (non-toEquals matchers)", function() {
+ it("should add the failure message to the DOM (non-toEquals matchers)", () => {
expectationResult = new jasmine.ExpectationResult({
- matcherName: "toBeNull", passed: false, message: "Expected 'a' to be null, but it was not"
+ matcherName: "toBeNull",
+ passed: false,
+ message: "Expected 'a' to be null, but it was not",
});
- spyOn(results, 'getItems').andReturn([expectationResult]);
+ spyOn(results, "getItems").andReturn([expectationResult]);
reporter.reportSpecResults(spec);
- var divs = body.getElementsByTagName("div");
- var errorDiv = findElement(divs, 'errorMessage');
- expect(errorDiv.innerHTML).toEqual("Expected 'a' to be null, but it was not");
+ const divs = body.getElementsByTagName("div");
+ const errorDiv = findElement(divs, "errorMessage");
+ 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() {
+ it("should add the failure message to the DOM (non-toEquals matchers) html escaping", () => {
expectationResult = new jasmine.ExpectationResult({
- matcherName: "toBeNull", passed: false, message: "Expected '1 < 2' to e null, & it was not"
+ matcherName: "toBeNull",
+ passed: false,
+ message: "Expected '1 < 2' to e null, & it was not",
});
- spyOn(results, 'getItems').andReturn([expectationResult]);
+ spyOn(results, "getItems").andReturn([expectationResult]);
reporter.reportSpecResults(spec);
- var divs = body.getElementsByTagName("div");
- var errorDiv = findElement(divs, 'errorMessage');
- expect(errorDiv.innerHTML).toEqual("Expected '1 < 2' to <b>e null, & it was not");
+ const divs = body.getElementsByTagName("div");
+ const errorDiv = findElement(divs, "errorMessage");
+ expect(errorDiv.innerHTML).toEqual(
+ "Expected '1 < 2' to <b>e null, & it was not"
+ );
});
});
- describe("duplicate example names", function() {
- it("should report failures correctly", function() {
- var suite1 = env.describe("suite", function() {
- env.it("will have log messages", function() {
+ describe("duplicate example names", () => {
+ it("should report failures correctly", () => {
+ env.describe("suite", () => {
+ env.it("will have log messages", function () {
this.log("this one passes!");
this.expect(true).toBeTruthy();
});
});
-
- var suite2 = env.describe("suite", function() {
- env.it("will have log messages", function() {
+
+ env.describe("suite", () => {
+ env.it("will have log messages", function () {
this.log("this one fails!");
this.expect(true).toBeFalsy();
});
@@ -183,30 +194,33 @@ describe("KoansRunner", function() {
env.addReporter(reporter);
env.execute();
- var divs = body.getElementsByTagName("div");
- var failedSpecDiv = findElement(divs, 'suite failed');
- expect(failedSpecDiv.className).toEqual('suite failed');
- expect(failedSpecDiv.innerHTML).toContain("damaging your karma");
- expect(failedSpecDiv.innerHTML).not.toContain("has expanded your awareness");
-
- var passedSpecDiv = findElement(divs, 'suite passed');
- expect(passedSpecDiv.className).toEqual('suite passed');
- expect(passedSpecDiv.innerHTML).toContain("has expanded your awareness");
- expect(passedSpecDiv.innerHTML).not.toContain("damaging your karma");
+ const divs = body.getElementsByTagName("div");
+ const failedSpecDiv = findElement(divs, "suite failed");
+ expect(failedSpecDiv.className).toEqual("suite failed");
+ expect(failedSpecDiv.innerHTML).toContain(
+ "continue thinking about this koan"
+ );
+ expect(failedSpecDiv.innerHTML).not.toContain("You understand that");
+
+ const passedSpecDiv = findElement(divs, "suite passed");
+ expect(passedSpecDiv.className).toEqual("suite passed");
+ expect(passedSpecDiv.innerHTML).toContain("You understand that");
+ expect(passedSpecDiv.innerHTML).not.toContain(
+ "continue thinking about this koan"
+ );
});
});
- describe('#reportSpecStarting', function() {
- var spec1;
- beforeEach(function () {
- env.describe("suite 1", function() {
- spec1 = env.it("spec 1", function() {
- });
+ describe("#reportSpecStarting", () => {
+ let spec1;
+ beforeEach(() => {
+ env.describe("suite 1", () => {
+ spec1 = env.it("spec 1", () => {});
});
});
- it('should not log running specs by default', function() {
- spyOn(reporter, 'log');
+ it("should not log running specs by default", () => {
+ spyOn(reporter, "log");
reporter.reportSpecStarting(spec1);
@@ -214,40 +228,40 @@ describe("KoansRunner", function() {
});
});
- describe('showing progress', function() {
- beforeEach(function() {
- env.describe("suite 1", function() {
+ describe("showing progress", () => {
+ beforeEach(() => {
+ env.describe("suite 1", () => {
env.it("spec A");
env.it("spec B");
});
- env.describe("suite 2", function() {
+ env.describe("suite 2", () => {
env.it("spec C");
});
});
- describe('subjects', function() {
- describe("with no failures", function() {
- beforeEach(function() {
+ describe("subjects", () => {
+ describe("with no failures", () => {
+ beforeEach(() => {
env.addReporter(reporter);
- env.execute();
+ env.execute();
});
- it("should have 2 subjects", function() {
+ it("should have 2 subjects", () => {
expect(reporter.noOfSubjects).toBe(2);
});
- it("should not have any failed subjects", function() {
+ it("should not have any failed subjects", () => {
expect(reporter.failedSubjects).toBe(0);
});
});
- describe("with 1 failure", function() {
- beforeEach(function() {
- env.describe("suite with error", function() {
- env.it("spec X", function() {
+ describe("with 1 failure", () => {
+ beforeEach(() => {
+ env.describe("suite with error", () => {
+ env.it("spec X", () => {
expect(true).toBeFalsey();
});
- env.it("spec Y", function() {
+ env.it("spec Y", () => {
expect(true).toBeFalsey();
});
});
@@ -256,24 +270,24 @@ describe("KoansRunner", function() {
env.execute();
});
- it("should have 3 subjects", function() {
+ it("should have 3 subjects", () => {
expect(reporter.noOfSubjects).toBe(3);
});
- it("should have a failure", function() {
+ it("should have a failure", () => {
expect(reporter.failedSubjects).toBe(1);
});
});
- describe("with 2 failures", function() {
- beforeEach(function() {
- env.describe("suite with error", function() {
- env.it("spec X", function() {
+ describe("with 2 failures", () => {
+ beforeEach(() => {
+ env.describe("suite with error", () => {
+ env.it("spec X", () => {
expect(true).toBeFalsey();
});
});
- env.describe("suite with error too", function() {
- env.it("spec Y", function() {
+ env.describe("suite with error too", () => {
+ env.it("spec Y", () => {
expect(true).toBeFalsey();
});
});
@@ -282,24 +296,24 @@ describe("KoansRunner", function() {
env.execute();
});
- it("should have 4 subjects", function() {
+ it("should have 4 subjects", () => {
expect(reporter.noOfSubjects).toBe(4);
- });
-
- it("should have 2 failures", function() {
+ });
+
+ it("should have 2 failures", () => {
expect(reporter.failedSubjects).toBe(2);
- });
+ });
});
- describe("with embedded suites only outer suites count as subjects", function() {
- beforeEach(function() {
- env.describe("outer suite", function() {
- env.it("spec for outer suite", function() {
+ describe("with embedded suites only outer suites count as subjects", () => {
+ beforeEach(() => {
+ env.describe("outer suite", () => {
+ env.it("spec for outer suite", () => {
expect(true).toBeFalsey();
});
- env.describe("inner suite", function() {
- env.it("spec for inner suite", function() {
+ env.describe("inner suite", () => {
+ env.it("spec for inner suite", () => {
expect(true).toBeFalsey();
});
});
@@ -309,28 +323,27 @@ describe("KoansRunner", function() {
env.execute();
});
- it("should have 3 suites", function() {
+ it("should have 3 suites", () => {
expect(reporter.noOfSubjects).toBe(3);
- });
-
- it("should have 1 failure", function() {
- expect(reporter.failedSubjects).toBe(1);
- });
+ });
+ it("should have 1 failure", () => {
+ expect(reporter.failedSubjects).toBe(1);
+ });
});
});
});
- describe("presentation", function() {
- describe("showing the suite description", function() {
- it("should prefix outer suite descriptions with 'Thinking'", function() {
- suite = fakeSuite("About Pies");
+ describe("presentation", () => {
+ describe("showing the suite description", () => {
+ it("should prefix outer suite descriptions with 'Thinking'", () => {
+ suite = fakeSuite("About Pies");
description = reporter.getSuiteDescription(suite);
expect(description).toEqual("Thinking About Pies");
});
- it("should prefix inner suite descriptions with 'Thinking'", function() {
+ it("should prefix inner suite descriptions with 'Thinking'", () => {
suite = fakeSuite("cherries");
suite.parentSuite = "Something";
description = reporter.getSuiteDescription(suite);
diff --git a/lib/jsTestDriver/JsTestDriver.jar b/lib/jsTestDriver/JsTestDriver.jar
deleted file mode 100644
index 8541aab30..000000000
Binary files a/lib/jsTestDriver/JsTestDriver.jar and /dev/null differ
diff --git a/lib/jsTestDriver/capture_browser.sh b/lib/jsTestDriver/capture_browser.sh
deleted file mode 100755
index e2cc1e4ea..000000000
--- a/lib/jsTestDriver/capture_browser.sh
+++ /dev/null
@@ -1 +0,0 @@
-java -jar JsTestDriver.jar --port 42442 --runnerMode DEBUG --browser /Applications/Firefox-3.app/Contents/MacOS/firefox-bin
\ No newline at end of file
diff --git a/lib/jsTestDriver/jsTestDriver.conf b/lib/jsTestDriver/jsTestDriver.conf
deleted file mode 100644
index 436f176a2..000000000
--- a/lib/jsTestDriver/jsTestDriver.conf
+++ /dev/null
@@ -1,16 +0,0 @@
-server: http://localhost:42442
-
-load:
- - src/dojo-release-1.5.0/dojo/dojo.js
- - src/dojo-release-1.5.0/dojox/lang/functional/*.js
- - src/*.js
-
- - src-test/PathToEnlightenment.js
- - src-test/AboutAsserts.js
- - src-test/AboutArrays.js
- - src-test/AboutFunctions.js
- - src-test/AboutObjects.js
- - src-test/AboutMutability.js
- - src-test/AboutLambda.js
- - src-test/AboutHigherOrderFunctions.js
- - src-test/ApplyingWhatWeveLearnt.js
diff --git a/lib/jsTestDriver/run_all_koans.sh b/lib/jsTestDriver/run_all_koans.sh
deleted file mode 100755
index 98ff7a8eb..000000000
--- a/lib/jsTestDriver/run_all_koans.sh
+++ /dev/null
@@ -1 +0,0 @@
-java -jar JsTestDriver.jar --reset --tests all
\ No newline at end of file
diff --git a/lib/underscore-min.js b/lib/underscore-min.js
deleted file mode 100644
index f502cf9f6..000000000
--- a/lib/underscore-min.js
+++ /dev/null
@@ -1,26 +0,0 @@
-// Underscore.js 1.1.6
-// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
-// Underscore is freely distributable under the MIT license.
-// Portions of Underscore are inspired or borrowed from Prototype,
-// Oliver Steele's Functional, and John Resig's Micro-Templating.
-// For all details and documentation:
-// http://documentcloud.github.com/underscore
-(function(){var p=this,C=p._,m={},i=Array.prototype,n=Object.prototype,f=i.slice,D=i.unshift,E=n.toString,l=n.hasOwnProperty,s=i.forEach,t=i.map,u=i.reduce,v=i.reduceRight,w=i.filter,x=i.every,y=i.some,o=i.indexOf,z=i.lastIndexOf;n=Array.isArray;var F=Object.keys,q=Function.prototype.bind,b=function(a){return new j(a)};typeof module!=="undefined"&&module.exports?(module.exports=b,b._=b):p._=b;b.VERSION="1.1.6";var h=b.each=b.forEach=function(a,c,d){if(a!=null)if(s&&a.forEach===s)a.forEach(c,d);else if(b.isNumber(a.length))for(var e=
-0,k=a.length;e=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,
-c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};h(a,function(a,b,f){b=c?c.call(d,a,b,f):a;bd?1:0}),"value")};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.zip=function(){for(var a=f.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),
-e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return function(){if(--a<1)return b.apply(this,arguments)}};b.keys=F||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)l.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a,
-b.identity)};b.functions=b.methods=function(a){return b.filter(b.keys(a),function(c){return b.isFunction(a[c])}).sort()};b.extend=function(a){h(f.call(arguments,1),function(b){for(var d in b)b[d]!==void 0&&(a[d]=b[d])});return a};b.defaults=function(a){h(f.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,c){if(a===c)return!0;var d=typeof a;if(d!=
-typeof c)return!1;if(a==c)return!0;if(!a&&c||a&&!c)return!1;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual)return a.isEqual(c);if(b.isDate(a)&&b.isDate(c))return a.getTime()===c.getTime();if(b.isNaN(a)&&b.isNaN(c))return!1;if(b.isRegExp(a)&&b.isRegExp(c))return a.source===c.source&&a.global===c.global&&a.ignoreCase===c.ignoreCase&&a.multiline===c.multiline;if(d!=="object")return!1;if(a.length&&a.length!==c.length)return!1;d=b.keys(a);var e=b.keys(c);if(d.length!=e.length)return!1;
-for(var f in a)if(!(f in c)||!b.isEqual(a[f],c[f]))return!1;return!0};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(l.call(a,c))return!1;return!0};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=n||function(a){return E.call(a)==="[object Array]"};b.isArguments=function(a){return!(!a||!l.call(a,"callee"))};b.isFunction=function(a){return!(!a||!a.constructor||!a.call||!a.apply)};b.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};
-b.isNumber=function(a){return!!(a===0||a&&a.toExponential&&a.toFixed)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===!0||a===!1};b.isDate=function(a){return!(!a||!a.getTimezoneOffset||!a.setUTCFullYear)};b.isRegExp=function(a){return!(!a||!a.test||!a.exec||!(a.ignoreCase||a.ignoreCase===!1))};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.noConflict=function(){p._=C;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=
-0;e/g,interpolate:/<%=([\s\S]+?)%>/g};b.template=function(a,c){var d=b.templateSettings;d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.interpolate,function(a,b){return"',"+b.replace(/\\'/g,"'")+",'"}).replace(d.evaluate||
-null,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');";d=new Function("obj",d);return c?d(c):d};var j=function(a){this._wrapped=a};b.prototype=j.prototype;var r=function(a,c){return c?b(a).chain():a},H=function(a,c){j.prototype[a]=function(){var a=f.call(arguments);D.call(a,this._wrapped);return r(c.apply(b,a),this._chain)}};b.mixin(b);h(["pop","push","reverse","shift","sort",
-"splice","unshift"],function(a){var b=i[a];j.prototype[a]=function(){b.apply(this._wrapped,arguments);return r(this._wrapped,this._chain)}});h(["concat","join","slice"],function(a){var b=i[a];j.prototype[a]=function(){return r(b.apply(this._wrapped,arguments),this._chain)}});j.prototype.chain=function(){this._chain=!0;return this};j.prototype.value=function(){return this._wrapped}})();