├── .gitignore
├── .gitmodules
├── LICENSE
├── test.html
├── README.markdown
├── specit.js
├── specit.tests.js
└── jquery-1.4.2.min.js
/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | *.swp
3 | *.swo
4 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "qunit"]
2 | path = qunit
3 | url = https://github.com/jquery/qunit.git
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010 Josh Clayton
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/test.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
19 |
20 |
21 |
SpecIt
22 |
23 |
24 |
25 |
26 |
27 |
28 |
Text
29 |
Text
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | # SpecIt
2 |
3 | ## There's some RSpec in your QUnit
4 |
5 | Let's face it: [QUnit](http://github.com/jquery/qunit) is pretty awesome, but just doesn't seem to read correctly.
6 |
7 | I don't have the patience to write my own JS testing framework so I figured I'd piggyback off of what QUnit provides.
8 |
9 | ## Example
10 |
11 | describe("SpecIt", function() {
12 | var john, cachedItems = [], something = false;
13 |
14 | before(function() {
15 | john = {name: "John Doe", age: 26};
16 | });
17 |
18 | after(function() {
19 | cachedItems = [];
20 | });
21 |
22 | it("should match on inclusion", function() {
23 | assert([1, 2]).should(include, 1, 2);
24 | assert({one: 1, two: 2}).should(include, "one");
25 | assert("string").should(include, "str");
26 | cachedItems.push(1);
27 | assert(cachedItems).should(include, 1);
28 | });
29 |
30 | it("should match by type comparison", function() {
31 | assert("string").should(beA, String);
32 | assert(function() {}).should(beA, Function);
33 | assert(true).should(beA, Boolean);
34 | assert({}).should(beAn, Object);
35 | });
36 |
37 | it("allows overriding variables", function() {
38 | john = {};
39 | assert(john).shouldNot(include, "name");
40 | });
41 |
42 | it("should use before blocks", function() {
43 | assert(john.name).should(eql, "John Doe");
44 | assert(john.age).should(beLessThan, 30);
45 | });
46 |
47 | it("should run after callbacks", function() {
48 | assert(cachedItems).should(beSimilarTo, []);
49 | });
50 |
51 | asyncIt("runs async tests correctly", function() {
52 | setTimeout(function() {
53 | something = true;
54 | }, 50);
55 |
56 | setTimeout(function() {
57 | assert(something).should(be);
58 | start();
59 | }, 100);
60 | });
61 | });
62 |
63 | ## Supported Matchers
64 |
65 | * include (checks presence within an object)
66 | * eql (checks equality with QUnit's equal)
67 | * beSimilarTo (checks equality with QUnit's deepEqual)
68 | * be (asserts true)
69 | * beA, beAn (checks type)
70 | * match (checks against a regular expression)
71 | * respondTo (checks that a function exists)
72 | * beLessThan (checks a number is less than another)
73 | * beLessThanOrEqualTo (checks a number is less than or equal to another)
74 | * beGreaterThan (checks a number is greater than another)
75 | * beGreaterThanOrEqualTo (checks a number is greater than or equal to another)
76 | * beEmpty (checks if an array, object literal, or string is empty)
77 | * beOnThePage (checks that an element is present on a page)
78 | * beToTheLeftOf (checks that an element is to the left of another element)
79 | * beToTheRightOf (checks that an element is to the right of another element)
80 | * beAbove (checks that an element is above another element)
81 |
82 | ## Other supported features
83 |
84 | * Before callbacks
85 | * After callbacks
86 |
87 | ## What's it do?
88 |
89 | I wrote some matchers and used QUnit's module and test methods, that's all. The test file is a great form of documentation and demonstrates everything SpecIt can do currently.
90 |
91 | ## Running the tests
92 |
93 | Open test.html in your favorite web browser. Qunit is a git submodule, so you'll want to grab it first.
94 |
95 | ## Note on Patches/Pull Requests
96 |
97 | * Fork the project.
98 | * Make your feature addition or bug fix.
99 | * Commit, do not mess with version or history.
100 | (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
101 | * Send me a pull request. Bonus points for topic branches.
102 |
103 | ## Copyright
104 |
105 | Copyright (c) 2010 Josh Clayton. Check the LICENSE for details.
106 |
--------------------------------------------------------------------------------
/specit.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | function objectToSpecIt(expectation, args) {
3 | var args = $.makeArray(args),
4 | matcherAndArgs = [args.shift()];
5 | $.each(args, function(i, item) { matcherAndArgs.push(item); });
6 | return SpecIt.expectations(this)[expectation].apply(this, matcherAndArgs);
7 | }
8 |
9 | var SpecIt = {
10 | currentExpectation: "should",
11 | assert: function(value) {
12 | return {
13 | should: function() { return objectToSpecIt.call(value, "should", arguments); },
14 | shouldNot: function() { return objectToSpecIt.call(value, "shouldNot", arguments); }
15 | };
16 | },
17 | describe: function(description, body) {
18 | this.currentTests = [];
19 | this.currentBefore = function() {};
20 | this.currentAfter = function() {};
21 | body();
22 | module(description, {setup: this.currentBefore, teardown: this.currentAfter});
23 | $.each(this.currentTests, function(i, currentTest) { currentTest(); });
24 | },
25 | it: function(description, body) {
26 | currentTests.push(function() { test(description, body); });
27 | },
28 | asyncIt: function(description, body) {
29 | currentTests.push(function() { asyncTest(description, body); });
30 | },
31 | before: function(callback) { this.currentBefore = callback; },
32 | after: function(callback) { this.currentAfter = callback; },
33 | expectations: function(current) {
34 | var expect = function(expectation, args) {
35 | var args = $.makeArray(args);
36 | SpecIt.currentExpectation = expectation;
37 | args.shift().apply(current, args);
38 | };
39 | return {
40 | should: function() { return expect("should", arguments); },
41 | shouldNot: function() { return expect("shouldNot", arguments); }
42 | }
43 | }
44 | };
45 |
46 | var Matcher = function(expectation, assertion, options) {
47 | var expected = options.expected.value,
48 | actual = options.actual.value,
49 | assert = options.assert,
50 | messageOptions = {},
51 | message = SpecIt.expectationMessage(expectation,
52 | expected,
53 | options.actual.messageValue || actual,
54 | messageOptions);
55 |
56 | if(SpecIt.currentExpectation === "shouldNot") {
57 | switch(assertion) {
58 | case "equal": assertion = "notEqual"; break;
59 | case "equals": assertion = "notEqual"; break;
60 | case "ok": assertion = "ok"; break;
61 | case "deepEqual": assertion = "notDeepEqual"; break;
62 | }
63 | if(assertion === "ok") { assert = !assert; }
64 | }
65 |
66 | if(assertion === "ok") {
67 | window[assertion](assert, message);
68 | } else {
69 | window[assertion](actual, expected, message);
70 | }
71 | };
72 |
73 | $.extend(SpecIt, {
74 | expectationMessage: function(matcher, expected, actual) {
75 | var matcherMessages = {
76 | include: "Expected {actual} {not} to include {expected}",
77 | eql: "Expected {actual} {not} to equal",
78 | beSimilarTo: "Expected {actual} {not} to be the same as",
79 | be: "Expected {actual} {not} to be true",
80 | beA: "Expected {actual} {not} to be a",
81 | beAn: "Expected {actual} {not} to be an",
82 | match: "Expected {actual} {not} to match {expected}",
83 | respondTo: "Expected {expected} {not} to be a method of {actual}",
84 | beLessThan: "Expected {actual} {not} to be less than {expected}",
85 | beLessThanOrEqualTo: "Expected {actual} {not} to be less than or equal to {expected}",
86 | beGreaterThan: "Expected {actual} {not} to be greater than {expected}",
87 | beGreaterThanOrEqualTo: "Expected {actual} {not} to be greater than or equal to {expected}",
88 | beOnThePage: "Expected {actual} {not} to be on the page",
89 | beEmpty: "Expected {actual} {not} to be empty",
90 | beToTheLeftOf: "Expected {actual} {not} to be to the left of {expected}",
91 | beToTheRightOf: "Expected {actual} {not} to be to the right of {expected}",
92 | beAbove: "Expected {actual} {not} to be above {expected}"
93 | }, message, options = arguments[3];
94 |
95 | message = matcherMessages[matcher];
96 |
97 | message = message.replace("{expected}", expected).replace("{actual}", JSON.stringify(actual));
98 |
99 | if(SpecIt.currentExpectation === "should") {
100 | message = message.replace("{not} ", "");
101 | } else {
102 | message = message.replace("{not}", "not");
103 | }
104 |
105 | return message;
106 | },
107 | matchers: {
108 | include: function() {
109 | var args = $.makeArray(arguments), expectation = true, actual = this;
110 | $.each(args, function(i, item) {
111 | if(actual.constructor == Object && actual.length == undefined) {
112 | expectation = false;
113 | if(item in actual) { expectation = true; }
114 | } else {
115 | if(actual.indexOf(item) < 0) { expectation = false; }
116 | }
117 | });
118 |
119 | Matcher("include", "ok",
120 | {assert: expectation,
121 | expected: {value: args, parse: true},
122 | actual: {value: actual, parse: true}});
123 | },
124 | eql: function() {
125 | Matcher("eql", "equal",
126 | {expected: {value: arguments[0], parse: true},
127 | actual: {value: this, parse: true}});
128 | },
129 | beSimilarTo: function() {
130 | Matcher("beSimilarTo", "deepEqual",
131 | {expected: {value: arguments[0], parse: true},
132 | actual: {value: this, parse: true}});
133 | },
134 | be: function() {
135 | Matcher("be", "ok",
136 | {assert: JSON.parse(JSON.stringify(this)),
137 | expected: {value: true, parse: true},
138 | actual: {value: this, parse: true}});
139 | },
140 | beA: function() {
141 | Matcher("beA", "equals",
142 | {expected: {value: arguments[0].name.toString(), parse: true},
143 | actual: {value: this.constructor.name, parse: true, messageValue: this}});
144 | },
145 | beAn: function() {
146 | Matcher("beAn", "equals",
147 | {expected: {value: arguments[0].name.toString(), parse: true},
148 | actual: {value: this.constructor.name, parse: true, messageValue: this}});
149 | },
150 | match: function() {
151 | Matcher("match", "ok",
152 | {assert: arguments[0].test(this),
153 | expected: {value: arguments[0], parse: true},
154 | actual: {value: this, parse: true}});
155 | },
156 | respondTo: function() {
157 | Matcher("respondTo", "ok",
158 | {assert: typeof this[arguments[0]] === "function",
159 | expected: {value: arguments[0], parse: true},
160 | actual: {value: this, parse: true}});
161 | },
162 | beLessThan: function() {
163 | Matcher("beLessThan", "ok",
164 | {assert: this < arguments[0],
165 | expected: {value: arguments[0], parse: true},
166 | actual: {value: this, parse: true}});
167 | },
168 | beLessThanOrEqualTo: function() {
169 | Matcher("beLessThanOrEqualTo", "ok",
170 | {assert: this <= arguments[0],
171 | expected: {value: arguments[0], parse: true},
172 | actual: {value: this, parse: true}});
173 | },
174 | beGreaterThan: function() {
175 | Matcher("beGreaterThan", "ok",
176 | {assert: this > arguments[0],
177 | expected: {value: arguments[0], parse: true},
178 | actual: {value: this, parse: true}});
179 | },
180 | beGreaterThanOrEqualTo: function() {
181 | Matcher("beGreaterThanOrEqualTo", "ok",
182 | {assert: this >= arguments[0],
183 | expected: {value: arguments[0], parse: true},
184 | actual: {value: this, parse: true}});
185 | },
186 | beOnThePage: function() {
187 | Matcher("beOnThePage", "ok",
188 | {assert: $(this).length > 0,
189 | expected: {value: arguments[0], parse: true},
190 | actual: {value: $(this).selector, parse: true}});
191 | },
192 | beEmpty: function() {
193 | var empty = true;
194 | if (this.constructor == Object && this.length == undefined) {
195 | for(var key in this) { empty = false; }
196 | } else {
197 | if(this.length > 0) { empty = false; }
198 | }
199 |
200 | Matcher("beEmpty", "ok",
201 | {assert: empty,
202 | expected: {value: arguments[0], parse: true},
203 | actual: {value: this, parse: true}});
204 | },
205 | beToTheLeftOf: function() {
206 | Matcher("beToTheLeftOf", "ok",
207 | {assert: $(this).offset().left < $(arguments[0]).offset().left,
208 | expected: {value: $(arguments[0]).selector, parse: true},
209 | actual: {value: $(this).selector, parse: true}});
210 | },
211 | beToTheRightOf: function() {
212 | Matcher("beToTheRightOf", "ok",
213 | {assert: ($(this).offset().left > ($(arguments[0]).offset().left + $(arguments[0]).width())),
214 | expected: {value: $(arguments[0]).selector, parse: true},
215 | actual: {value: $(this).selector, parse: true}});
216 | },
217 | beAbove: function() {
218 | Matcher("beAbove", "ok",
219 | {assert: $(this).offset().top < $(arguments[0]).offset().top,
220 | expected: {value: $(arguments[0]).selector, parse: true},
221 | actual: {value: $(this).selector, parse: true}});
222 | }
223 | }
224 | });
225 |
226 | for(var matcher in SpecIt.matchers) {
227 | window[matcher] = SpecIt.matchers[matcher];
228 | }
229 |
230 | window.describe = SpecIt.describe;
231 | window.it = SpecIt.it;
232 | window.asyncIt = SpecIt.asyncIt;
233 | window.before = SpecIt.before;
234 | window.after = SpecIt.after;
235 | window.assert = SpecIt.assert;
236 | })();
237 |
--------------------------------------------------------------------------------
/specit.tests.js:
--------------------------------------------------------------------------------
1 | describe("SpecIt", function() {
2 | it("should match on inclusion", function() {
3 | assert([1, 2]).should(include, 1);
4 | assert([1, 2]).should(include, 1, 2);
5 | assert({one: 1, two: 2}).should(include, "one");
6 |
7 | assert([1, 2]).shouldNot(include, [1, 2]);
8 | assert([1, 2]).shouldNot(include, [1, 2], 1, 2);
9 | assert([1, 2]).shouldNot(include, 3);
10 | assert([1, 2]).shouldNot(include, 3, 4);
11 | assert({one: 1}).shouldNot(include, "two");
12 |
13 | assert("string").should(include, "string");
14 | assert("string").should(include, "ring");
15 | assert("string").should(include, "tr");
16 |
17 | assert("string").shouldNot(include, " string");
18 | assert("string").shouldNot(include, "string ");
19 | assert("string").shouldNot(include, "cat");
20 | });
21 |
22 | it("should match on equality", function() {
23 | assert("string").should(eql, "string");
24 | assert(1).should(eql, 1);
25 | assert(true).should(eql, true);
26 |
27 | assert("string").shouldNot(eql, "junk");
28 | assert([]).shouldNot(eql, []);
29 | assert(["tree"]).shouldNot(eql, ["tree"]);
30 | assert({}).shouldNot(eql, {});
31 | assert(true).shouldNot(eql, false);
32 | });
33 |
34 | it("should match on similarity", function() {
35 | assert("string").should(beSimilarTo, "string");
36 | assert(1).should(beSimilarTo, 1);
37 | assert(true).should(beSimilarTo, true);
38 | assert([]).should(beSimilarTo, []);
39 | assert(["tree"]).should(beSimilarTo, ["tree"]);
40 | assert({}).should(beSimilarTo, {});
41 | assert({a: 1}).should(beSimilarTo, {"a": 1});
42 |
43 | assert("string").shouldNot(beSimilarTo, "junk");
44 | assert(true).shouldNot(beSimilarTo, false);
45 | assert({a: 1}).shouldNot(beSimilarTo, {b: 1});
46 | });
47 |
48 | it("should match on truthiness", function() {
49 | assert("string").should(be);
50 | assert(true).should(be);
51 | assert(1).should(be);
52 |
53 | assert("").shouldNot(be);
54 | assert(false).shouldNot(be);
55 | assert(0).shouldNot(be);
56 | });
57 |
58 | it("should match by type comparison", function() {
59 | assert("string").should(beA, String);
60 | assert(function() {}).should(beA, Function);
61 | assert(true).should(beA, Boolean);
62 | assert({}).should(beAn, Object);
63 | assert([]).should(beAn, Array);
64 | assert(1).should(beA, Number);
65 | assert(/regular-expression/).should(beA, RegExp);
66 |
67 | assert("string").shouldNot(beAn, Object);
68 | assert("string").shouldNot(beA, Number);
69 | assert([]).shouldNot(beAn, Object);
70 | });
71 |
72 | it("should match against regular expressions", function() {
73 | assert("string").should(match, /string/);
74 | assert("202-555-1212").should(match, /\d{3}.\d{3}.\d{4}/);
75 | assert("string").shouldNot(match, /\\\\w{10}/);
76 | });
77 |
78 | it("should match on method presence", function() {
79 | var myObject = {
80 | attribute1: 1,
81 | booleanAttr: true,
82 | methodAttr: function() {}
83 | };
84 |
85 | assert(myObject).should(respondTo, "methodAttr");
86 | assert(myObject).shouldNot(respondTo, "attribute1");
87 | assert(myObject).shouldNot(respondTo, "booleanAttr");
88 | assert(myObject).shouldNot(respondTo, "junkMethod");
89 |
90 | var Person = function(options) {
91 | this.name = options.name || "";
92 | this.age = options.age || 13;
93 | this.sayHi = function() {
94 | return "Hello; my name is " + this.name;
95 | };
96 | return this;
97 | };
98 |
99 | var john = new Person({name: "John Doe", age: 35});
100 | assert(john).should(respondTo, "sayHi");
101 | assert(john).shouldNot(respondTo, "name");
102 | assert(john).shouldNot(respondTo, "age");
103 | assert(john).shouldNot(respondTo, "sayGoodbye");
104 | });
105 |
106 | it("should match on less than", function() {
107 | assert( 2).should(beLessThan, 5);
108 | assert( -5).should(beLessThan, 0);
109 | assert( 0).should(beLessThan, 0.1);
110 | assert( 5).shouldNot(beLessThan, 3);
111 | assert(0.1).shouldNot(beLessThan, 0);
112 | assert(0.1).shouldNot(beLessThan, 0.05);
113 | assert( 5).shouldNot(beLessThan, 5);
114 |
115 | assert("awesome").should(beLessThan, "great");
116 | });
117 |
118 | it("should match on less than or equal to", function() {
119 | assert( 2).should(beLessThanOrEqualTo, 5);
120 | assert( -5).should(beLessThanOrEqualTo, 0);
121 | assert( 0).should(beLessThanOrEqualTo, 0.1);
122 | assert( 5).should(beLessThanOrEqualTo, 5);
123 | assert(0.1).should(beLessThanOrEqualTo, 0.1);
124 |
125 | assert( 5).shouldNot(beLessThanOrEqualTo, 3);
126 | assert(0.1).shouldNot(beLessThanOrEqualTo, 0);
127 | assert(0.1).shouldNot(beLessThanOrEqualTo, 0.05);
128 |
129 | assert("awesome").should(beLessThanOrEqualTo, "great");
130 | assert("great").should(beLessThanOrEqualTo, "great");
131 | });
132 |
133 | it("should match on greater than", function() {
134 | assert( 2).should(beGreaterThan, 1);
135 | assert( -5).should(beGreaterThan, -10);
136 | assert( 0).should(beGreaterThan, -0.1);
137 | assert( 5).shouldNot(beGreaterThan, 30);
138 | assert(0.1).shouldNot(beGreaterThan, 0.2);
139 | assert(0.01).shouldNot(beGreaterThan, 0.05);
140 | assert( 5).shouldNot(beGreaterThan, 5);
141 |
142 | assert("awesome").should(beGreaterThan, "absolute");
143 | });
144 |
145 | it("should match on greater than or equal to", function() {
146 | assert( 2).should(beGreaterThanOrEqualTo, 1);
147 | assert( -5).should(beGreaterThanOrEqualTo, -10);
148 | assert( 0).should(beGreaterThanOrEqualTo, -0.1);
149 | assert( 5).should(beGreaterThanOrEqualTo, 5);
150 | assert( 5).shouldNot(beGreaterThanOrEqualTo, 30);
151 | assert(0.1).shouldNot(beGreaterThanOrEqualTo, 0.2);
152 | assert(0.01).shouldNot(beGreaterThanOrEqualTo, 0.05);
153 |
154 | assert("awesome").should(beGreaterThanOrEqualTo, "awesome");
155 | });
156 |
157 | it("should match on emptiness", function() {
158 | assert([]).should(beEmpty);
159 | assert({}).should(beEmpty);
160 | assert(0).should(beEmpty);
161 | assert(5).should(beEmpty);
162 | assert("").should(beEmpty);
163 | assert([1, 2]).shouldNot(beEmpty);
164 | assert({one: 1}).shouldNot(beEmpty);
165 | assert("one").shouldNot(beEmpty);
166 | });
167 |
168 | it("should match on elements on a page", function() {
169 | $(".workspace").append("
");
170 | assert($(".workspace .great")).should(beOnThePage);
171 | assert($(".workspace .non-existant")).shouldNot(beOnThePage);
172 | $(".workspace").empty();
173 | });
174 | });
175 |
176 | var john, beforeCallbackTest, afterCallbackTest;
177 |
178 | describe("SpecIt with a before callback", function() {
179 | var jane = {name: "Jane"};
180 |
181 | before(function() {
182 | beforeCallbackTest = true;
183 | john = {name: "John Doe"};
184 | });
185 |
186 | it("should support before", function() {
187 | ok(beforeCallbackTest);
188 | equal(afterCallbackTest, undefined);
189 | });
190 |
191 | it("should run before every test", function() {
192 | john.name = "Wrong name";
193 | jane.age = 26;
194 | });
195 |
196 | it("should run before every test", function() {
197 | equals(john.name, "John Doe");
198 | });
199 |
200 | it("should not know attributes from another before callback", function() {
201 | equals(john.age, undefined);
202 | });
203 |
204 | it("should not modify attributes on a local object if untouched in before", function() {
205 | equals(jane.age, 26);
206 | });
207 | });
208 |
209 | // the john object will carry over, but the jane object will not
210 | describe("SpecIt with a different before callback", function() {
211 | before(function() { john.age = 35; });
212 |
213 | it("should not run other describes' before callbacks", function() {
214 | john.name = "whatever";
215 | equals(john.age, 35);
216 | });
217 |
218 | it("should not run other describes' before callbacks", function() {
219 | equals(john.name, "whatever");
220 | equals(john.age, 35);
221 | });
222 |
223 | it("should not know of other objects in a different describe", function() {
224 | equals(typeof jane, "undefined");
225 | });
226 | });
227 |
228 | describe("SpecIt with an after callback", function() {
229 | var changedFromAfterCallback = "unchanged";
230 |
231 | after(function() {
232 | changedFromAfterCallback = "changed";
233 | });
234 |
235 | it("should not call after callback until after a test is run", function() {
236 | equals(changedFromAfterCallback, "unchanged");
237 | });
238 |
239 | it("should call the after callback the first test is run", function() {
240 | equals(changedFromAfterCallback, "changed");
241 | changedFromAfterCallback = "bogus";
242 | });
243 |
244 | it("should call the after callback after each test is run", function() {
245 | equals(changedFromAfterCallback, "changed");
246 | });
247 | });
248 |
249 | describe("SpecIt handling before and after", function() {
250 | before(function() { $("body").append("
"); });
251 | after (function() { $("#crazy").remove(); });
252 |
253 | it("should run before callbacks correctly", function() {
254 | $("#crazy").html("awesome div");
255 | assert($("#crazy:contains(awesome div)")).should(beOnThePage);
256 | });
257 |
258 | it("should run after callbacks correctly", function() {
259 | assert($("#crazy").length).should(eql, 1);
260 | assert($("#crazy:contains(awesome div)")).shouldNot(beOnThePage);
261 | });
262 | });
263 |
264 | describe("SpecIt should know relative positions", function() {
265 | it("should know if an element is to the left of another", function() {
266 | assert($(".left-right-correct .left")).should(beToTheLeftOf, ".left-right-correct .right");
267 | assert($(".left-right-correct .text-1")).should(beToTheLeftOf, ".left-right-correct .text-2");
268 |
269 | assert($(".left-right-correct .right")).shouldNot(beToTheLeftOf, ".left-right-correct .left");
270 | assert($(".left-right-broken .left")).shouldNot(beToTheLeftOf, ".left-right-broken .right");
271 | });
272 |
273 | it("should know if an element is to the right of", function() {
274 | assert($(".left-right-correct .right")).should(beToTheRightOf, ".left-right-correct .left");
275 | assert($(".left-right-correct .text-2")).shouldNot(beToTheRightOf, ".left-right-correct .text-1");
276 |
277 | assert($(".left-right-correct .left")).shouldNot(beToTheRightOf, ".left-right-correct .right");
278 | assert($(".left-right-broken .right")).shouldNot(beToTheRightOf, ".left-right-broken .left");
279 | });
280 |
281 | it("should know if an element is to the above", function() {
282 | assert($(".left-right-broken .left")).should(beAbove, ".left-right-broken .right");
283 | assert($(".left-right-correct .text-2")).shouldNot(beAbove, ".left-right-correct .text-1");
284 |
285 | assert($(".left-right-correct .left")).shouldNot(beAbove, ".left-right-correct .right");
286 | assert($(".left-right-correct .right")).shouldNot(beAbove, ".left-right-correct .left");
287 | });
288 | });
289 |
290 | describe("SpecIt handles async tests", function() {
291 | var something = false;
292 |
293 | asyncIt("runs async tests correctly", function() {
294 | setTimeout(function() {
295 | something = true;
296 | }, 50);
297 |
298 | setTimeout(function() {
299 | assert(something).should(be);
300 | start();
301 | }, 100);
302 | });
303 | });
304 |
--------------------------------------------------------------------------------
/jquery-1.4.2.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * jQuery JavaScript Library v1.4.2
3 | * http://jquery.com/
4 | *
5 | * Copyright 2010, John Resig
6 | * Dual licensed under the MIT or GPL Version 2 licenses.
7 | * http://jquery.org/license
8 | *
9 | * Includes Sizzle.js
10 | * http://sizzlejs.com/
11 | * Copyright 2010, The Dojo Foundation
12 | * Released under the MIT, BSD, and GPL Licenses.
13 | *
14 | * Date: Sat Feb 13 22:33:48 2010 -0500
15 | */
16 | (function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
21 | Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
22 | (d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
23 | a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
24 | "find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
25 | function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b