hamcrest4qunit 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.sublime-project
19
+ *.sublime-workspace
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in hamcrest4qunit.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,38 @@
1
+ # Hamcrest4qunit
2
+
3
+ Hamcrest4QUnit is a port of the [Hamcrest](http://code.google.com/p/hamcrest/)
4
+ matchers set intended to work with [QUnit](http://docs.jquery.com/Qunit).
5
+
6
+ Sarting with the version 1.3.0, `hamcrest4qunit` is provided as a ruby gem.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'hamcrest4qunit'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install hamcrest4qunit
21
+
22
+ ## Usage
23
+
24
+ Add this line to your tests manifest:
25
+
26
+ //= require hamcrest4qunit
27
+
28
+ To include the `hamcrest4qunit` test suite in your own tests, add this line to your tests manifest:
29
+
30
+ //= require hamcrest4qunit/test
31
+
32
+ ## Contributing
33
+
34
+ 1. Fork it
35
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
36
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
37
+ 4. Push to the branch (`git push origin my-new-feature`)
38
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ class h4q.Description
2
+ constructor: (@message="", @diff=null) ->
3
+
4
+ toString: -> @message
5
+ hasDiff: -> @diff?
6
+ clearMessage: -> @message = ""; this
7
+ appendText: (msg) -> @append msg; this
8
+
9
+ appendValue: (val) ->
10
+ @append "<span class='value'>#{QUnit.jsDump.parse val}</span>"
11
+ this
12
+
13
+ appendRawValue: (val) ->
14
+ @append "<span class='value'>#{val}</span>"
15
+ this
16
+
17
+ appendDescriptionOf: (matcher) ->
18
+ matcher.describeTo this
19
+ this
20
+
21
+ append: (s) ->
22
+ @message += " " if @message isnt ""
23
+ @message += s
@@ -0,0 +1,158 @@
1
+ TAB_STRING = " "
2
+
3
+ h4q = {}
4
+ window.h4q = h4q
5
+
6
+ h4q.tokenReplace = (s) ->
7
+ args = h4q.argumentsToArray arguments
8
+ args.shift()
9
+
10
+ if args.length > 0 and args[0] instanceof Object
11
+ kwargs = args[0]
12
+ s = s.replace /\${([^}]+)}/g, ->
13
+ key = arguments[1]
14
+ if kwargs.hasOwnProperty(key) then kwargs[key] else arguments[0]
15
+
16
+ args.shift()
17
+
18
+ s.replace /\$([0-9]+)/g, ->
19
+ index = parseInt arguments[1]
20
+ if index < args.length then args[index] else arguments[0]
21
+
22
+ h4q.argumentsToArray = (args) -> arg for arg in args
23
+
24
+ h4q.sortProperties = (o) ->
25
+ b = (k for k of o)
26
+ b.sort()
27
+ b
28
+
29
+ h4q.getType = (thing) ->
30
+ return "Null" unless thing?
31
+
32
+ results = /\[object (.{1,})\]/.exec Object.prototype.toString.call thing
33
+
34
+ if results and results.length > 1 then results[1] else ""
35
+
36
+ h4q.getTypeName = (type) ->
37
+ results = /function (.{1,})\(/.exec type.toString()
38
+ if results and results.length > 1 then results[1] else ""
39
+
40
+ h4q.aPrefix = (s) -> if s.substr(0,1) in "aeiouAEIOU" then "an" else "a"
41
+
42
+ h4q.escapeHtml = (s) ->
43
+ return "" unless s?
44
+
45
+ s = String(s)
46
+ s.replace /[\&"<>\\]/g, (s) ->
47
+ switch s
48
+ when "&" then "&amp"
49
+ when "\\" then "\\\\"
50
+ when '"' then '\"'
51
+ when "<" then "&lt"
52
+ when ">" then "&gt"
53
+ else s
54
+
55
+ h4q.nodeToString = (node, indent="") ->
56
+ unless node? and node instanceof Node
57
+ throw new Error
58
+ message: "nodeToString expect a valid node as argument"
59
+
60
+ isRootCall = indent is ""
61
+ tag = String(node.nodeName).toLowerCase()
62
+ attr = h4q.attrToString node
63
+ content = h4q.contentToString node, indent
64
+
65
+ s = "#{indent}<#{tag}#{attr}>#{content}</#{tag}>"
66
+
67
+ if isRootCall then h4q.escapeHtml s else s
68
+
69
+ h4q.attrToString = (node) ->
70
+ exludedAttrs = [
71
+ "length", "item", "getNamedItem",
72
+ "setNamedItem", "removeNamedItem", "getNamedItemNS",
73
+ "setNamedItemNS", "removeNamedItemNS"
74
+ ]
75
+
76
+ s = ""
77
+ alreadyPrinted = []
78
+ for attr of node.attributes
79
+ name = node.attributes[attr].name
80
+
81
+ unless attr in exludedAttrs or name in alreadyPrinted
82
+ s += " #{name}=\"#{node.attributes[attr].value}\""
83
+ alreadyPrinted.push name
84
+
85
+ return s
86
+
87
+ h4q.contentToString = (node, indent) ->
88
+ s = ""
89
+ nodes = node.childNodes
90
+ return "" unless nodes?
91
+
92
+ l = nodes.length
93
+ contentIsOnlyText = true
94
+ res = []
95
+ for node in nodes
96
+
97
+ if node.nodeType is 3 then res.push node.textContent
98
+ else
99
+ res.push h4q.nodeToString node, indent + TAB_STRING
100
+ contentIsOnlyText = false
101
+
102
+ if contentIsOnlyText then s += res.join ""
103
+ else
104
+ res = res.map (o, i) ->
105
+ if /</.exec o then o else indent + TAB_STRING + o
106
+
107
+ s += "\n#{res.join "\n"}"
108
+
109
+ s + (if l > 0 and not contentIsOnlyText then "\n#{indent}" else "")
110
+
111
+ h4q.push = (result, mismatchMsg, expectedMsg, message) ->
112
+ details =
113
+ result: result
114
+ message: message
115
+
116
+ resultMsg = "<tr class='test-actual'>
117
+ <th>#{if result? then "And:" else "But:"}</th>
118
+ <td><pre>#{mismatchMsg.message}</pre></td>
119
+ </tr>"
120
+
121
+ diffMsg = if mismatchMsg.hasDiff()
122
+ "<tr class='test-diff'>
123
+ <th>Diff: </th>
124
+ <td><pre>#{mismatchMsg.diff}</pre></td>
125
+ </tr>"
126
+ else
127
+ ""
128
+
129
+ output = "<span class='test-message'>#{message}</span>
130
+ <table>
131
+ <tr class='test-expected'>
132
+ <th>Expected: </th>
133
+ <td><pre>#{expectedMsg.message}</pre></td>
134
+ </tr>
135
+ #{resultMsg}
136
+ #{diffMsg}
137
+ </table>"
138
+
139
+ QUnit.log details
140
+ QUnit.config.current.assertions.push
141
+ result: result,
142
+ message: output
143
+
144
+ h4q.assertThat = (target, matcher=h4q.equalTo(true), description=null) ->
145
+ throw new Error message: "Unsupported assertion" if arguments.length is 0
146
+
147
+ expectedMsg = new Description()
148
+ mismatchMsg = new Description()
149
+
150
+ matcher = h4q.equalTo matcher unless matcher instanceof Matcher
151
+
152
+ expectedMsg.appendDescriptionOf( matcher )
153
+ result = matcher.matches( target, mismatchMsg )
154
+
155
+ h4q.push result,
156
+ mismatchMsg,
157
+ expectedMsg,
158
+ if message? then message else if result? then "okay" else "failed"
@@ -0,0 +1,7 @@
1
+ #= require ./h4q
2
+ #= require ./description
3
+ #= require ./matcher
4
+ #= require ./matchers
5
+
6
+ # Matchers are available as top level functions.
7
+ window[k] = v for k,v of window.h4q
@@ -0,0 +1,31 @@
1
+ class h4q.Matcher
2
+ constructor: (options) ->
3
+
4
+ unless options._matches
5
+ throw new Error
6
+ message: "Improperly configured matcher, the matcher
7
+ expect a _matches method"
8
+
9
+ if typeof options._matches isnt "function"
10
+ throw new Error
11
+ message: "Improperly configured matcher, the _matches
12
+ argument must be a function"
13
+
14
+ unless options._describeTo
15
+ throw new Error
16
+ message: "Improperly configured matcher, the matcher expect
17
+ a _describeTo method"
18
+
19
+ if typeof options._describeTo isnt "function"
20
+ throw new Error
21
+ message: "Improperly configured matcher, the _describeTo
22
+ argument must be a function"
23
+
24
+ @[k] = v for k, v of options
25
+
26
+ matches: (v, mismatchMsg) ->
27
+ @_matches.call this, v, mismatchMsg
28
+
29
+ describeTo: ( msg ) ->
30
+ @_describeTo.call this, msg
31
+
@@ -0,0 +1,221 @@
1
+ h4q.arrayWithLength = (l) ->
2
+ if isNaN l
3
+ throw new Error message: "length argument must be a valid number"
4
+ if l < 0
5
+ throw new Error
6
+ message: "length argument must be greater than or equal to 0"
7
+
8
+ new Matcher
9
+ length: l
10
+ _matches: (v,msg) ->
11
+ msg.appendText("was").appendValue(v)
12
+ v? and
13
+ v instanceof Array and
14
+ v.length == @length
15
+
16
+ _describeTo: (msg) ->
17
+ msg.appendText("an Array with")
18
+ .appendValue(@length)
19
+ .appendText(if @length > 1 then "items" else "item")
20
+
21
+ h4q.emptyArray = ->
22
+ new Matcher
23
+ _matches: (v,msg) ->
24
+ msg.appendText("was").appendValue(v)
25
+ v? and
26
+ v instanceof Array and
27
+ v.length is 0
28
+
29
+ _describeTo: (msg) ->
30
+ msg.appendText "an empty Array"
31
+
32
+ h4q.array = ->
33
+ args = h4q.argumentsToArray arguments
34
+ matchers = []
35
+ l = args.length
36
+
37
+ return h4q.emptyArray() if l is 0
38
+
39
+ for m in args
40
+ if m instanceof Matcher
41
+ matchers.push m
42
+ else
43
+ matchers.push equalTo m
44
+
45
+ new Matcher
46
+ matchers: matchers
47
+ _matches: (v,msg) ->
48
+ l = @matchers.length
49
+
50
+ unless v?
51
+ msg.appendText("was").appendValue(null)
52
+ false
53
+ else unless v instanceof Array
54
+ msg.appendText("was").appendValue(v)
55
+ false
56
+ else if v.length isnt l
57
+ msg.appendText("was an Array with")
58
+ .appendValue(v.length)
59
+ .appendText(if v.length > 1 then "items" else "item")
60
+ false
61
+ else
62
+ a = @matchers
63
+ hasError = false
64
+ msg.appendText("was").appendRawValue("[").appendText("\n")
65
+
66
+ v.forEach (o,i) ->
67
+ msgtmp = new Description()
68
+ res = a[i].matches o, msgtmp
69
+ msg.appendText " "
70
+ if res
71
+ msg.appendValue o
72
+ else
73
+ msg.appendText msgtmp.message
74
+ hasError = true
75
+
76
+ msg.appendText ",\n" if i < l-1
77
+
78
+ msg.appendRawValue "\n]"
79
+
80
+ not hasError
81
+
82
+ _describeTo: (msg) ->
83
+ l = @matchers.length
84
+
85
+ msg.appendText("an Array with")
86
+ .appendValue(l)
87
+ .appendText(if l > 1 then "items" else "item")
88
+ .appendText("like").appendRawValue("[").appendText("\n ")
89
+
90
+ for matcher, i in @matchers
91
+ msg.appendDescriptionOf matcher
92
+ msg.appendText(",\n ") if i < l-1
93
+
94
+ msg.appendRawValue("\n]")
95
+
96
+ h4q.everyItem = (m) ->
97
+ unless m?
98
+ throw new Error message: "everyItem must receive an argument"
99
+
100
+ m = equalTo m unless m instanceof Matcher
101
+
102
+ new Matcher
103
+ matcher: m
104
+ _matches: (v, msg) ->
105
+ unless v?
106
+ msg.appendText("was").appendValue(null)
107
+ false
108
+ else unless v instanceof Array
109
+ msg.appendText("was").appendValue(v)
110
+ false
111
+ else
112
+ for val, i in v
113
+ msgtmp = new Description()
114
+ unless @matcher.matches val, msgtmp
115
+ msg.appendText(msgtmp.message)
116
+ .appendText("at index")
117
+ .appendValue(i)
118
+ return false
119
+
120
+ msg.appendText("was").appendValue(v)
121
+ true
122
+
123
+ _describeTo: (msg) ->
124
+ msg.appendText("an Array of which every item is")
125
+ .appendDescriptionOf( @matcher )
126
+
127
+ h4q.hasItem = (m) ->
128
+ unless m?
129
+ throw new Error message: "hasItem must receive an argument"
130
+
131
+ m = equalTo m unless m instanceof Matcher
132
+
133
+ new Matcher
134
+ matcher: m
135
+ _matches: (v,msg) ->
136
+ unless v?
137
+ msg.appendText("was").appendValue(null)
138
+ false
139
+ unless v instanceof Array
140
+ msg.appendText("was").appendValue(v)
141
+ false
142
+ else
143
+ l = v.length
144
+ for val in v
145
+ msgtmp = new Description()
146
+ if @matcher.matches val, msgtmp
147
+ msg.appendText("was").appendValue(v)
148
+ return true
149
+
150
+ msg.appendText "can't find any"
151
+ false
152
+
153
+ _describeTo: (msg) ->
154
+ msg.appendText("an Array containing").appendDescriptionOf(@matcher)
155
+
156
+ h4q.hasItems = ->
157
+ args = h4q.argumentsToArray arguments
158
+ if args.length is 0
159
+ throw new Error message: "hasItems must receive at least one argument"
160
+
161
+ matchers = []
162
+ for m in args
163
+ if m instanceof Matcher
164
+ matchers.push m
165
+ else
166
+ matchers.push equalTo m
167
+
168
+ new Matcher
169
+ matchers: matchers
170
+ _matches: (v,msg) ->
171
+ unless v?
172
+ msg.appendText("was").appendValue(null)
173
+ false
174
+ unless v instanceof Array
175
+ msg.appendText("was").appendValue(v)
176
+ false
177
+ else
178
+ l = @matchers.length
179
+ k = v.length
180
+ gres = true
181
+ mismsg = []
182
+ msgtmp = new Description()
183
+ for m in @matchers
184
+ res = false
185
+ for val, j in v
186
+ res = m.matches(val, msgtmp) or res
187
+
188
+ unless res
189
+ d = new Description()
190
+ d.appendDescriptionOf m
191
+ mismsg.push d
192
+
193
+ gres = res and gres
194
+
195
+ if gres
196
+ msg.appendText("was").appendValue(v)
197
+ else
198
+ l = mismsg.length
199
+ if l is 1
200
+ msg.appendText("can't find").appendText( mismsg )
201
+ else
202
+ msg.appendText("can't find neither")
203
+ for v, i in mismsg
204
+ if i is l-1
205
+ msg.appendText "nor"
206
+ else if i > 0
207
+ msg.appendText ","
208
+
209
+ msg.appendText v
210
+ gres
211
+
212
+ _describeTo: (msg) ->
213
+ msg.appendText "an Array containing"
214
+ for m, i in @matchers
215
+ if i is @matchers.length - 1
216
+ msg.appendText "and"
217
+ else if i > 0
218
+ msg.appendText ","
219
+
220
+ msg.appendDescriptionOf m
221
+