shenandoah 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. data/.braids +8 -0
  2. data/.document +5 -0
  3. data/.gitignore +6 -0
  4. data/ChangeLog.markdown +6 -0
  5. data/LICENSE +20 -0
  6. data/LICENSE-Blue-Ridge +20 -0
  7. data/LICENSE-Screw.Unit +22 -0
  8. data/LICENSE-Smoke +22 -0
  9. data/README.markdown +260 -0
  10. data/Rakefile +70 -0
  11. data/VERSION.yml +4 -0
  12. data/lib/shenandoah/buildr.rb +9 -0
  13. data/lib/shenandoah/buildr/locator.rb +17 -0
  14. data/lib/shenandoah/buildr/shenandoah_tasks.rb +18 -0
  15. data/lib/shenandoah/buildr/test_framework.rb +28 -0
  16. data/lib/shenandoah/css/screw.css +90 -0
  17. data/lib/shenandoah/javascript/browser/runner.js +34 -0
  18. data/lib/shenandoah/javascript/common/jquery-1.3.2.js +4376 -0
  19. data/lib/shenandoah/javascript/common/jquery.fn.js +29 -0
  20. data/lib/shenandoah/javascript/common/jquery.print.js +109 -0
  21. data/lib/shenandoah/javascript/common/screw.behaviors.js +129 -0
  22. data/lib/shenandoah/javascript/common/screw.builder.js +104 -0
  23. data/lib/shenandoah/javascript/common/screw.events.js +45 -0
  24. data/lib/shenandoah/javascript/common/screw.matchers.js +254 -0
  25. data/lib/shenandoah/javascript/common/screw.mocking.js +22 -0
  26. data/lib/shenandoah/javascript/common/smoke.core.js +6 -0
  27. data/lib/shenandoah/javascript/common/smoke.mock.js +130 -0
  28. data/lib/shenandoah/javascript/common/smoke.stub.js +29 -0
  29. data/lib/shenandoah/javascript/console/consoleReportForRake.js +32 -0
  30. data/lib/shenandoah/javascript/console/env.rhino.js +8841 -0
  31. data/lib/shenandoah/javascript/console/js.jar +0 -0
  32. data/lib/shenandoah/javascript/console/runner.js +43 -0
  33. data/lib/shenandoah/javascript/console/shell.js.erb +23 -0
  34. data/lib/shenandoah/locator.rb +17 -0
  35. data/lib/shenandoah/runner.rb +69 -0
  36. data/lib/shenandoah/server.rb +88 -0
  37. data/lib/shenandoah/server/views/index.haml +12 -0
  38. data/lib/shenandoah/tasks.rb +58 -0
  39. data/shenandoah.gemspec +133 -0
  40. data/spec/shenandoah/buildr/locator_spec.rb +33 -0
  41. data/spec/shenandoah/buildr/shenandoah_tasks_spec.rb +27 -0
  42. data/spec/shenandoah/buildr/spec_helper.rb +2 -0
  43. data/spec/shenandoah/buildr/test_framework_spec.rb +77 -0
  44. data/spec/shenandoah/locator_spec.rb +74 -0
  45. data/spec/shenandoah/runner_spec.rb +110 -0
  46. data/spec/shenandoah/server_spec.rb +216 -0
  47. data/spec/shenandoah/tasks_spec.rb +76 -0
  48. data/spec/spec_helper.rb +36 -0
  49. metadata +232 -0
@@ -0,0 +1,29 @@
1
+ (function($) {
2
+ $.fn.fn = function() {
3
+ var self = this;
4
+ var extension = arguments[0], name = arguments[0];
5
+ if (typeof name == "string") {
6
+ return apply(self, name, $.makeArray(arguments).slice(1, arguments.length));
7
+ } else {
8
+ $.each(extension, function(key, value) {
9
+ define(self, key, value);
10
+ });
11
+ return self;
12
+ }
13
+ }
14
+ function define(self, name, fn) {
15
+ self.data(namespacedName(name), fn);
16
+ };
17
+ function apply(self, name, args) {
18
+ var result;
19
+ self.each(function(i, item) {
20
+ var fn = $(item).data(namespacedName(name));
21
+ if (fn) result = fn.apply(item, args)
22
+ else throw(name + " is not defined");
23
+ });
24
+ return result;
25
+ };
26
+ function namespacedName(name) {
27
+ return 'fn.' + name;
28
+ }
29
+ })(jQuery);
@@ -0,0 +1,109 @@
1
+ (function($) {
2
+
3
+ function print_array(obj, opts) {
4
+ var result = [];
5
+ for (var i = 0; i < Math.min(opts.max_array, obj.length); i++)
6
+ result.push($.print(obj[i], $.extend({}, opts, { max_array: 3, max_string: 40 })));
7
+
8
+ if (obj.length > opts.max_array)
9
+ result.push((obj.length - opts.max_array) + ' more...');
10
+ if (result.length == 0) return "[]"
11
+ return "[ " + result.join(", ") + " ]";
12
+ }
13
+
14
+ function print_element(obj) {
15
+ if (obj.nodeType == 1) {
16
+ var result = [];
17
+ var properties = [ 'className', 'id' ];
18
+ var extra = {
19
+ 'input': ['type', 'name', 'value'],
20
+ 'a': ['href', 'target'],
21
+ 'form': ['method', 'action'],
22
+ 'script': ['src'],
23
+ 'link': ['href'],
24
+ 'img': ['src']
25
+ };
26
+
27
+ $.each(properties.concat(extra[obj.tagName.toLowerCase()] || []), function(){
28
+ if (obj[this])
29
+ result.push(' ' + this.replace('className', 'class') + "=" + $.print(obj[this]))
30
+ });
31
+ return "<" + obj.tagName.toLowerCase()
32
+ + result.join('') + ">";
33
+ }
34
+ }
35
+
36
+ function print_object(obj, opts) {
37
+ var seen = opts.seen || [ obj ];
38
+
39
+ var result = [], key, value;
40
+ for (var k in obj) {
41
+ if (obj.hasOwnProperty(k) && $.inArray(obj[k], seen) < 0) {
42
+ seen.push(obj[k]);
43
+ value = $.print(obj[k], $.extend({}, opts, { max_array: 6, max_string: 40, seen: seen }));
44
+ } else
45
+ value = "...";
46
+ result.push(k + ": " + value);
47
+ }
48
+ if (result.length == 0) return "{}";
49
+ return "{ " + result.join(", ") + " }";
50
+ }
51
+
52
+ function print_string(value, opts) {
53
+ var character_substitutions = {
54
+ '\b': '\\b',
55
+ '\t': '\\t',
56
+ '\n': '\\n',
57
+ '\f': '\\f',
58
+ '\r': '\\r',
59
+ '"' : '\\"',
60
+ '\\': '\\\\'
61
+ };
62
+ var r = /["\\\x00-\x1f\x7f-\x9f]/g;
63
+
64
+ var str = r.test(value)
65
+ ? '"' + value.replace(r, function (a) {
66
+ var c = character_substitutions[a];
67
+ if (c) return c;
68
+ c = a.charCodeAt();
69
+ return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
70
+ }) + '"'
71
+ : '"' + value + '"';
72
+ if (str.length > opts.max_string)
73
+ return str.slice(0, opts.max_string + 1) + '..."';
74
+ else
75
+ return str;
76
+ }
77
+
78
+ $.print = function(obj, options) {
79
+ var opts = $.extend({}, { max_array: 10, max_string: 100 }, options);
80
+
81
+ if (typeof obj == 'undefined')
82
+ return "undefined";
83
+ else if (typeof obj == 'boolean')
84
+ return obj.toString();
85
+ else if (typeof obj == 'number')
86
+ return obj.toString();
87
+ else if (!obj)
88
+ return "null";
89
+ else if (typeof obj == 'string')
90
+ return print_string(obj, opts);
91
+ else if (obj instanceof RegExp)
92
+ return obj.toString();
93
+ else if (obj instanceof Array || obj.callee || obj.item)
94
+ return print_array(obj, opts);
95
+ else if (typeof obj == 'function' || obj instanceof Function)
96
+ return obj.toString().match(/^([^)]*\))/)[1];
97
+ else if (obj.nodeType)
98
+ return print_element(obj);
99
+ else if (obj instanceof jQuery)
100
+ return "$(" + $.print(obj.get()) + ")";
101
+ else if (obj instanceof Error)
102
+ return print_object(obj, $.extend({}, options, { max_string: 200 }));
103
+ else if (obj instanceof Object)
104
+ return print_object(obj, opts);
105
+ else
106
+ return obj.toString().replace(/\n\s*/g, '');
107
+ }
108
+
109
+ })(jQuery);
@@ -0,0 +1,129 @@
1
+ (function($) {
2
+ $(Screw).bind('loaded', function() {
3
+ $('.status').fn({
4
+ display: function() {
5
+ $(this).html(
6
+ $('.passed').length + $('.failed').length + ' test(s), ' + $('.failed').length + ' failure(s)<br />' +
7
+ ((new Date() - Screw.suite_start_time)/1000.0).toString() + " seconds elapsed"
8
+ );
9
+ }
10
+ });
11
+
12
+ $('.describe').fn({
13
+ parent: function() {
14
+ return $(this).parent('.describes').parent('.describe');
15
+ },
16
+
17
+ run_befores: function() {
18
+ $(this).fn('parent').fn('run_befores');
19
+ $(this).children('.befores').children('.before').fn('run');
20
+ },
21
+
22
+ run_afters: function() {
23
+ $(this).fn('parent').fn('run_afters');
24
+ $(this).children('.afters').children('.after').fn('run');
25
+ },
26
+
27
+ enqueue: function() {
28
+ $(this).children('.its').children('.it').fn('enqueue');
29
+ $(this).children('.describes').children('.describe').fn('enqueue');
30
+ },
31
+
32
+ selector: function() {
33
+ return $(this).fn('parent').fn('selector')
34
+ + ' > .describes > .describe:eq(' + $(this).parent('.describes').children('.describe').index(this) + ')';
35
+ }
36
+ });
37
+
38
+ $('body > .describe').fn({
39
+ selector: function() { return 'body > .describe'; }
40
+ });
41
+
42
+ $('.it').fn({
43
+ parent: function() {
44
+ return $(this).parent('.its').parent('.describe');
45
+ },
46
+
47
+ run: function() {
48
+ var self = this;
49
+ $(this).data('screwunit.run_segment', function () {
50
+ $(self).fn('parent').fn('run_befores');
51
+ $(self).data('screwunit.run')();
52
+ });
53
+ $(this).fn('run_segment');
54
+ },
55
+
56
+ run_segment: function() {
57
+ var failure = null;
58
+ try {
59
+ $(this).data('screwunit.run_segment')();
60
+ } catch(e) {
61
+ if (e instanceof Screw.Wait) {
62
+ var self = this;
63
+ $(this).data('timeout', setTimeout(function () {
64
+ $(self).data('screwunit.run_segment', e.func)
65
+ $(self).fn("run_segment");
66
+ }, e.delay));
67
+ return;
68
+ } else {
69
+ failure = [e];
70
+ }
71
+ }
72
+
73
+ try {
74
+ if (failure) {
75
+ $(this).trigger('failed', failure);
76
+ } else {
77
+ $(this).trigger('passed');
78
+ }
79
+ } finally {
80
+ $(this).fn('parent').fn('run_afters')
81
+ $(this).removeData('timeout')
82
+ }
83
+ },
84
+
85
+ enqueue: function() {
86
+ var self = $(this).trigger('enqueued');
87
+ $(Screw)
88
+ .queue(function() {
89
+ self.fn('run');
90
+ if (self.data('timeout')) {
91
+ // If the test contains pending async elements, wait for
92
+ // them to complete.
93
+ var watcher = setInterval(function () {
94
+ if (!self.data('timeout')) {
95
+ clearInterval(watcher);
96
+ $(Screw).dequeue();
97
+ }
98
+ }, 100);
99
+ } else {
100
+ // Otherwise, immediately start the next test.
101
+ setTimeout(function() { $(Screw).dequeue(); }, 0);
102
+ }
103
+ });
104
+ },
105
+
106
+ selector: function() {
107
+ return $(this).fn('parent').fn('selector')
108
+ + ' > .its > .it:eq(' + $(this).parent('.its').children('.it').index(this) + ')';
109
+ }
110
+ });
111
+
112
+ $('body .before').fn({
113
+ run: function() { $(this).data('screwunit.run')(); }
114
+ });
115
+
116
+ $('body .after').fn({
117
+ run: function() {
118
+ $(this).data('screwunit.run')(); }
119
+ });
120
+
121
+ $(Screw).trigger('before');
122
+ var to_run = unescape(location.search.slice(1)) || 'body > .describe > .describes > .describe';
123
+ $(to_run)
124
+ .focus()
125
+ .eq(0).trigger('scroll').end()
126
+ .fn('enqueue');
127
+ $(Screw).queue(function() { $(Screw).trigger('after') });
128
+ });
129
+ })(jQuery);
@@ -0,0 +1,104 @@
1
+ var Screw = (function($) {
2
+ var screw = {
3
+ Unit: function(fn) {
4
+ var wrappedFn;
5
+ if(fn.length == 0) {
6
+ var contents = fn.toString().match(/^[^\{]*{((.*\n*)*)}/m)[1];
7
+ wrappedFn = new Function("matchers", "specifications",
8
+ "with (specifications) { with (matchers) { " + contents + " } }"
9
+ );
10
+ } else {
11
+ wrappedFn = function(matchers, specifications) {
12
+ var screwContext = {};
13
+ for(var method in matchers) {
14
+ screwContext[method] = matchers[method];
15
+ }
16
+ for(var method in specifications) {
17
+ screwContext[method] = specifications[method];
18
+ }
19
+ fn(screwContext);
20
+ }
21
+ }
22
+
23
+ $(Screw).queue(function() {
24
+ Screw.Specifications.context.push($('body > .describe'));
25
+ wrappedFn.call(this, Screw.Matchers, Screw.Specifications);
26
+ Screw.Specifications.context.pop();
27
+ $(this).dequeue();
28
+ });
29
+ },
30
+
31
+ Wait: function (fn, ms) {
32
+ this.func = fn;
33
+ this.delay = ms;
34
+ },
35
+
36
+ Specifications: {
37
+ context: [],
38
+
39
+ describe: function(name, fn) {
40
+ var describe = $('<li class="describe"></li>')
41
+ .append($('<h1></h1>').text(name))
42
+ .append('<ol class="befores"></ol>')
43
+ .append('<ul class="its"></ul>')
44
+ .append('<ul class="describes"></ul>')
45
+ .append('<ol class="afters"></ol>');
46
+
47
+ this.context.push(describe);
48
+ fn.call();
49
+ this.context.pop();
50
+
51
+ this.context[this.context.length-1]
52
+ .children('.describes')
53
+ .append(describe);
54
+ },
55
+
56
+ it: function(name, fn) {
57
+ var it = $('<li class="it"></li>')
58
+ .append($('<h2></h2>').text(name))
59
+ .data('screwunit.run', fn);
60
+
61
+ this.context[this.context.length-1]
62
+ .children('.its')
63
+ .append(it);
64
+ },
65
+
66
+ before: function(fn) {
67
+ var before = $('<li class="before"></li>')
68
+ .data('screwunit.run', fn);
69
+
70
+ this.context[this.context.length-1]
71
+ .children('.befores')
72
+ .append(before);
73
+ },
74
+
75
+ after: function(fn) {
76
+ var after = $('<li class="after"></li>')
77
+ .data('screwunit.run', fn);
78
+
79
+ this.context[this.context.length-1]
80
+ .children('.afters')
81
+ .append(after);
82
+ },
83
+
84
+ wait: function(fn, ms) {
85
+ throw new Screw.Wait(fn, ms);
86
+ }
87
+ }
88
+ };
89
+
90
+ $(screw).queue(function() { $(screw).trigger('loading') });
91
+ $(window).load(function(){
92
+ $('<div class="describe"></div>')
93
+ .append('<h3 class="status"></h3>')
94
+ .append('<ol class="befores"></ol>')
95
+ .append('<ul class="describes"></ul>')
96
+ .append('<ol class="afters"></ol>')
97
+ .appendTo('body');
98
+
99
+ $(screw).dequeue();
100
+ $(screw).trigger('loaded');
101
+ });
102
+
103
+ return screw;
104
+ })(jQuery);
@@ -0,0 +1,45 @@
1
+ (function($) {
2
+ $(Screw)
3
+ .bind('loaded', function() {
4
+ $('.describe, .it')
5
+ .click(function() {
6
+ document.location = location.href.split('?')[0] + '?' + $(this).fn('selector');
7
+ return false;
8
+ })
9
+ .focus(function() {
10
+ return $(this).addClass('focused');
11
+ })
12
+ .bind('scroll', function() {
13
+ document.body.scrollTop = $(this).offset().top;
14
+ });
15
+
16
+ $('.it')
17
+ .bind('enqueued', function() {
18
+ $(this).addClass('enqueued');
19
+ })
20
+ .bind('running', function() {
21
+ $(this).addClass('running');
22
+ })
23
+ .bind('passed', function() {
24
+ $(this).addClass('passed');
25
+ })
26
+ .bind('failed', function(e, reason) {
27
+ $(this)
28
+ .addClass('failed')
29
+ .append($('<p class="error"></p>').text(reason.message || reason.toString()));
30
+
31
+ var file = reason.fileName || reason.sourceURL;
32
+ var line = reason.lineNumber || reason.line;
33
+ if (file || line) {
34
+ $(this).append($('<p class="error"></p>').text('line ' + line + ', ' + file));
35
+ }
36
+ });
37
+ })
38
+ .bind('before', function() {
39
+ Screw.suite_start_time = new Date();
40
+ $('.status').text('Running...');
41
+ })
42
+ .bind('after', function() {
43
+ $('body .status').fn('display');
44
+ });
45
+ })(jQuery);
@@ -0,0 +1,254 @@
1
+ Screw.Matchers = (function($) {
2
+ return matchers = {
3
+ expect: function(actual) {
4
+ var funcname = function(f) {
5
+ var s = f.toString().match(/function (\w*)/)[1];
6
+ if ((s == null) || (s.length == 0)) return "anonymous";
7
+ return s;
8
+ };
9
+
10
+ var stacktrace = function() {
11
+ var s = "";
12
+ for(var a = arguments.caller; a != null; a = a.caller) {
13
+ s += funcname(a.callee) + "\n";
14
+ if (a.caller == a) break;
15
+ }
16
+ return s;
17
+ };
18
+
19
+ return {
20
+ to: function(matcher, expected, not) {
21
+ var matched = matcher.match(expected, actual);
22
+ if (not ? matched : !matched) {
23
+ throw(matcher.failure_message(expected, actual, not));
24
+ }
25
+ },
26
+
27
+ to_not: function(matcher, expected) {
28
+ this.to(matcher, expected, true);
29
+ }
30
+ }
31
+ },
32
+
33
+ equal: {
34
+ match: function(expected, actual) {
35
+ if(expected == actual) return true;
36
+ if(actual == undefined) return false;
37
+
38
+ if (expected instanceof Array) {
39
+ for (var i = 0; i < actual.length; i++)
40
+ if (!Screw.Matchers.equal.match(expected[i], actual[i])) return false;
41
+ return actual.length == expected.length;
42
+ } else if (expected instanceof Object) {
43
+ for (var key in expected)
44
+ if (!this.match(expected[key], actual[key])) return false;
45
+ for (var key in actual)
46
+ if (!this.match(actual[key], expected[key])) return false;
47
+ return true;
48
+ }
49
+ return false;
50
+ },
51
+
52
+ failure_message: function(expected, actual, not) {
53
+ return 'expected ' + $.print(actual) + (not ? ' to not equal ' : ' to equal ') + $.print(expected);
54
+ }
55
+ },
56
+
57
+ be_gt: {
58
+ match: function(expected, actual) {
59
+ return actual > expected;
60
+ },
61
+
62
+ failure_message: function(expected, actual, not) {
63
+ return 'expected ' + $.print(actual) + (not ? ' to not ' : ' to ') + 'be greater than ' + $.print(expected);
64
+ }
65
+ },
66
+
67
+ be_gte: {
68
+ match: function(expected, actual) {
69
+ return actual >= expected;
70
+ },
71
+
72
+ failure_message: function(expected, actual, not) {
73
+ return 'expected ' + $.print(actual) + (not ? ' to not ' : ' to ') + 'be greater than or equal to ' + $.print(expected);
74
+ }
75
+ },
76
+
77
+ be_lt: {
78
+ match: function(expected, actual) {
79
+ return actual < expected;
80
+ },
81
+
82
+ failure_message: function(expected, actual, not) {
83
+ return 'expected ' + $.print(actual) + (not ? ' to not ' : ' to ') + 'be less than ' + $.print(expected);
84
+ }
85
+ },
86
+
87
+ be_lte: {
88
+ match: function(expected, actual) {
89
+ return actual <= expected;
90
+ },
91
+
92
+ failure_message: function(expected, actual, not) {
93
+ return 'expected ' + $.print(actual) + (not ? ' to not ' : ' to ') + 'be less than or equal to ' + $.print(expected);
94
+ }
95
+ },
96
+
97
+ match: {
98
+ match: function(expected, actual) {
99
+ if (expected.constructor == RegExp)
100
+ return expected.exec(actual.toString());
101
+ else
102
+ return actual.indexOf(expected) > -1;
103
+ },
104
+
105
+ failure_message: function(expected, actual, not) {
106
+ return 'expected ' + $.print(actual) + (not ? ' to not match ' : ' to match ') + $.print(expected);
107
+ }
108
+ },
109
+
110
+ include: {
111
+ match: function(expected, actual) {
112
+ return $.inArray(expected, actual) >= 0;
113
+ },
114
+
115
+ failure_message: function(expected, actual, not) {
116
+ return 'expected ' + $.print(actual) + (not ? ' to not include ' : ' to include ') + $.print(expected);
117
+ }
118
+ },
119
+
120
+ be_empty: {
121
+ match: function(expected, actual) {
122
+ if (actual.length == undefined) throw(actual.toString() + " does not respond to length");
123
+
124
+ return actual.length == 0;
125
+ },
126
+
127
+ failure_message: function(expected, actual, not) {
128
+ return 'expected ' + $.print(actual) + (not ? ' to not be empty' : ' to be empty');
129
+ }
130
+ },
131
+
132
+ be_blank: {
133
+ match: function(expected, actual) {
134
+ if (actual == undefined) return true;
135
+ if (typeof(actual) == "string") actual = actual.replace(/^\s*(.*?)\s*$/, "$1");
136
+ return Screw.Matchers.be_empty.match(expected, actual);
137
+ },
138
+
139
+ failure_message: function(expected, actual, not) {
140
+ return 'expected ' + $.print(actual) + (not ? ' to not be blank' : ' to be blank');
141
+ }
142
+ },
143
+
144
+ have_length: {
145
+ match: function(expected, actual) {
146
+ if (actual.length == undefined) throw(actual.toString() + " does not respond to length");
147
+
148
+ return actual.length == expected;
149
+ },
150
+
151
+ failure_message: function(expected, actual, not) {
152
+ return 'expected ' + $.print(actual) + (not ? ' to not' : ' to') + ' have length ' + expected;
153
+ }
154
+ },
155
+
156
+ be_null: {
157
+ match: function(expected, actual) {
158
+ return actual == null;
159
+ },
160
+
161
+ failure_message: function(expected, actual, not) {
162
+ return 'expected ' + $.print(actual) + (not ? ' to not be null' : ' to be null');
163
+ }
164
+ },
165
+
166
+ be_undefined: {
167
+ match: function(expected, actual) {
168
+ return actual == undefined;
169
+ },
170
+
171
+ failure_message: function(expected, actual, not) {
172
+ return 'expected ' + $.print(actual) + (not ? ' to not be undefined' : ' to be undefined');
173
+ }
174
+ },
175
+
176
+ be_true: {
177
+ match: function(expected, actual) {
178
+ return actual;
179
+ },
180
+
181
+ failure_message: function(expected, actual, not) {
182
+ return 'expected ' + $.print(actual) + (not ? ' to not be true' : ' to be true');
183
+ }
184
+ },
185
+
186
+ be_false: {
187
+ match: function(expected, actual) {
188
+ return !actual;
189
+ },
190
+
191
+ failure_message: function(expected, actual, not) {
192
+ return 'expected ' + $.print(actual) + (not ? ' to not be false' : ' to be false');
193
+ }
194
+ },
195
+
196
+ match_html: {
197
+ munge: function(mungee) {
198
+ if (mungee instanceof jQuery) {
199
+ mungee = mungee.html();
200
+ } else if (typeof(mungee) == "string") {
201
+ var span = document.createElement("span");
202
+ span.innerHTML = mungee;
203
+ mungee = span.innerHTML;
204
+ }
205
+
206
+ var regEx = /\sjQuery\d+=['"]\d+['"]/g;
207
+ mungee = mungee.replace(regEx, "");
208
+
209
+ return mungee;
210
+ },
211
+
212
+ match: function(expected, actual) {
213
+ var trimmedExpected = this.munge(expected);
214
+ var trimmedActual = this.munge(actual);
215
+ return trimmedActual.indexOf(trimmedExpected) > -1;
216
+ },
217
+
218
+ failure_message: function(expected, actual, not) {
219
+ var trimmedExpected = this.munge(expected);
220
+ var trimmedActual = this.munge(actual);
221
+ return 'expected ' + $.print(trimmedActual, { max_string: 300 }) +
222
+ (not ? ' to not contain ' : ' to contain ') + $.print(trimmedExpected, { max_string: 300 });
223
+ }
224
+ },
225
+
226
+ match_selector: {
227
+ match: function(expected, actual) {
228
+ if (!(actual instanceof jQuery)) {
229
+ throw expected.toString() + " must be an instance of jQuery to match against a selector"
230
+ }
231
+
232
+ return actual.is(expected);
233
+ },
234
+
235
+ failure_message: function(expected, actual, not) {
236
+ return 'expected ' + $.print(actual) + (not ? ' to not match selector ' : ' to match selector ') + expected;
237
+ }
238
+ },
239
+
240
+ contain_selector: {
241
+ match: function(expected, actual) {
242
+ if (!(actual instanceof jQuery)) {
243
+ throw expected.toString() + " must be an instance of jQuery to match against a selector"
244
+ }
245
+
246
+ return actual.find(expected).length > 0;
247
+ },
248
+
249
+ failure_message: function(expected, actual, not) {
250
+ return 'expected ' + $.print(actual) + (not ? ' to not contain selector ' : ' to contain selector ') + expected;
251
+ }
252
+ }
253
+ }
254
+ })(jQuery);