hqmf2js 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.gitignore +10 -0
  2. data/.travis.yml +17 -0
  3. data/Gemfile +41 -0
  4. data/Gemfile.lock +202 -0
  5. data/README.md +7 -0
  6. data/Rakefile +22 -0
  7. data/VERSION +1 -0
  8. data/app/assets/javascripts/hqmf_util.js.coffee +776 -0
  9. data/app/assets/javascripts/logging_utils.js.coffee +150 -0
  10. data/app/assets/javascripts/patient_api_extension.js.coffee +36 -0
  11. data/app/assets/javascripts/specifics.js.coffee +462 -0
  12. data/bin/hqmf2js.rb +25 -0
  13. data/config/warble.rb +144 -0
  14. data/hqmf2js.gemspec +20 -0
  15. data/lib/config/codes.xml +1935 -0
  16. data/lib/generator/characteristic.js.erb +19 -0
  17. data/lib/generator/codes_to_json.rb +81 -0
  18. data/lib/generator/converter.rb +60 -0
  19. data/lib/generator/data_criteria.js.erb +47 -0
  20. data/lib/generator/derived_data.js.erb +5 -0
  21. data/lib/generator/js.rb +263 -0
  22. data/lib/generator/measure_period.js.erb +18 -0
  23. data/lib/generator/patient_data.js.erb +22 -0
  24. data/lib/generator/population_criteria.js.erb +4 -0
  25. data/lib/generator/precondition.js.erb +14 -0
  26. data/lib/hqmf2js.rb +20 -0
  27. data/lib/hquery/engine.rb +4 -0
  28. data/lib/tasks/codes.rake +12 -0
  29. data/lib/tasks/coffee.rake +15 -0
  30. data/lib/tasks/convert.rake +47 -0
  31. data/lib/tasks/cover_me.rake +8 -0
  32. data/test/fixtures/NQF59New.xml +1047 -0
  33. data/test/fixtures/codes/codes.xls +0 -0
  34. data/test/fixtures/codes/codes.xml +1941 -0
  35. data/test/fixtures/i2b2.xml +305 -0
  36. data/test/fixtures/invalid/missing_id.xml +18 -0
  37. data/test/fixtures/invalid/unknown_criteria_type.xml +16 -0
  38. data/test/fixtures/invalid/unknown_demographic_entry.xml +16 -0
  39. data/test/fixtures/invalid/unknown_population_type.xml +9 -0
  40. data/test/fixtures/invalid/unknown_value_type.xml +18 -0
  41. data/test/fixtures/js/59New.js +366 -0
  42. data/test/fixtures/js/test1.js +356 -0
  43. data/test/fixtures/js/test2.js +366 -0
  44. data/test/fixtures/json/0043.json +6 -0
  45. data/test/fixtures/json/0043_hqmf1.json +1 -0
  46. data/test/fixtures/json/0043_hqmf2.json +172 -0
  47. data/test/fixtures/json/59New.json +1352 -0
  48. data/test/fixtures/patient_api.js +2823 -0
  49. data/test/fixtures/patients/francis_drake.json +1180 -0
  50. data/test/fixtures/patients/larry_vanderman.json +645 -0
  51. data/test/test_helper.rb +58 -0
  52. data/test/unit/codes_to_json_test.rb +38 -0
  53. data/test/unit/effective_date_test.rb +48 -0
  54. data/test/unit/hqmf_from_json_javascript_test.rb +108 -0
  55. data/test/unit/hqmf_javascript_test.rb +175 -0
  56. data/test/unit/library_function_test.rb +553 -0
  57. data/test/unit/specifics_test.rb +757 -0
  58. metadata +183 -0
@@ -0,0 +1,553 @@
1
+ require_relative '../test_helper'
2
+ require 'hquery-patient-api'
3
+
4
+ class LibraryFunctionTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @context = get_js_context(HQMF2JS::Generator::JS.library_functions)
8
+ @context.eval("Specifics.initialize()")
9
+ end
10
+
11
+
12
+ def test_library_function_parses
13
+ @context.eval('hQuery == undefined').must_equal false
14
+ @context.eval('typeof hQuery.Patient').must_equal "function"
15
+ @context.eval('typeof allTrue').must_equal "function"
16
+ @context.eval('typeof atLeastOneTrue').must_equal "function"
17
+ end
18
+
19
+ def test_all_true
20
+ @context.eval('allTrue(new Boolean(false),new Boolean(false),new Boolean(false)).isTrue()').must_equal false
21
+ @context.eval('allTrue(new Boolean(false),new Boolean(true),new Boolean(false)).isTrue()').must_equal false
22
+ @context.eval('allTrue(new Boolean(true),new Boolean(true),new Boolean(true)).isTrue()').must_equal true
23
+ @context.eval('allTrue().isTrue()').must_equal false
24
+ end
25
+
26
+ def test_at_least_one_true
27
+ @context.eval('atLeastOneTrue(new Boolean(true),new Boolean(false),new Boolean(false)).isTrue()').must_equal true
28
+ @context.eval('atLeastOneTrue(new Boolean(true),new Boolean(true),new Boolean(true)).isTrue()').must_equal true
29
+ @context.eval('atLeastOneTrue(new Boolean(false),new Boolean(false),new Boolean(false)).isTrue()').must_equal false
30
+ @context.eval('atLeastOneTrue().isTrue()').must_equal false
31
+ end
32
+
33
+ def test_all_false
34
+ @context.eval('allFalse(new Boolean(false),new Boolean(false),new Boolean(false)).isTrue()').must_equal true
35
+ @context.eval('allFalse(new Boolean(false),new Boolean(true),new Boolean(false)).isTrue()').must_equal false
36
+ @context.eval('allFalse(new Boolean(true),new Boolean(true),new Boolean(true)).isTrue()').must_equal false
37
+ @context.eval('allFalse().isTrue()').must_equal false
38
+ end
39
+
40
+ def test_at_least_one_false
41
+ @context.eval('atLeastOneFalse(new Boolean(true),new Boolean(false),new Boolean(false)).isTrue()').must_equal true
42
+ @context.eval('atLeastOneFalse(new Boolean(true),new Boolean(true),new Boolean(true)).isTrue()').must_equal false
43
+ @context.eval('atLeastOneFalse(new Boolean(false),new Boolean(false),new Boolean(false)).isTrue()').must_equal true
44
+ @context.eval('atLeastOneFalse().isTrue()').must_equal false
45
+ end
46
+
47
+ def test_patient_extensions
48
+ @context.eval('typeof hQuery.Patient.prototype.procedureResults').must_equal "function"
49
+ @context.eval('typeof hQuery.Patient.prototype.laboratoryTests').must_equal "function"
50
+ @context.eval('typeof hQuery.Patient.prototype.allMedications').must_equal "function"
51
+ @context.eval('typeof hQuery.Patient.prototype.allProblems').must_equal "function"
52
+ @context.eval('typeof hQuery.Patient.prototype.allDevices').must_equal "function"
53
+ @context.eval('typeof hQuery.Patient.prototype.activeDiagnoses').must_equal "function"
54
+ @context.eval('typeof hQuery.Patient.prototype.inactiveDiagnoses').must_equal "function"
55
+ @context.eval('typeof hQuery.Patient.prototype.resolvedDiagnoses').must_equal "function"
56
+ end
57
+
58
+ def test_code_list
59
+ @context.eval('(new CodeList({"foo": [10,11]})).match(10)').must_equal true
60
+ @context.eval('(new CodeList({"foo": [10,11]})).match({"code": 10})').must_equal true
61
+ @context.eval('(new CodeList({"foo": [10,11]})).match(12)').must_equal false
62
+ @context.eval('(new CodeList({"foo": [10,11]})).match({"code": 12})').must_equal false
63
+ end
64
+
65
+ def test_pq
66
+ pq = "new PQ(1, 'mo')"
67
+ pq2 = "new PQ(2, 'mo')"
68
+ val = "{'scalar': 0}"
69
+ val1 = "{'scalar': 1}"
70
+ val2 = "{'scalar': 2}"
71
+ assert_equal 1, @context.eval("#{pq}.value")
72
+ assert_equal "mo", @context.eval("#{pq}.unit")
73
+ assert @context.eval("#{pq}.lessThan(3)")
74
+ assert @context.eval("#{pq}.greaterThan(0)")
75
+ assert @context.eval("#{pq}.match(1)")
76
+ assert @context.eval("#{pq}.lessThan(#{pq2})")
77
+ assert @context.eval("#{pq2}.greaterThan(#{pq})")
78
+ assert @context.eval("#{pq}.match(#{val1})")
79
+ assert @context.eval("#{pq}.lessThan(#{val2})")
80
+ assert @context.eval("#{pq}.greaterThan(#{val})")
81
+ end
82
+
83
+ def test_ts
84
+ # TS - Timestamp 2010-01-01
85
+ ts = 'new TS("20110101")'
86
+ ts2 = 'new TS("20100101")'
87
+ ts3 = 'new TS("20120101")'
88
+ assert_equal 2011, @context.eval("#{ts}.asDate().getFullYear()")
89
+ assert_equal 0, @context.eval("#{ts}.asDate().getMonth()")
90
+ assert_equal 1, @context.eval("#{ts}.asDate().getDate()")
91
+ assert_equal 2012, @context.eval("#{ts}.add(new PQ(1, 'a')).asDate().getFullYear()")
92
+ assert_equal 2, @context.eval("#{ts}.add(new PQ(1, 'd')).asDate().getDate()")
93
+ assert_equal 8, @context.eval("#{ts}.add(new PQ(1, 'wk')).asDate().getDate()")
94
+ assert_equal 1, @context.eval("#{ts}.add(new PQ(1, 'h')).asDate().getHours()")
95
+ assert_equal 5, @context.eval("#{ts}.add(new PQ(5, 'min')).asDate().getMinutes()")
96
+ assert_equal 11, @context.eval("#{ts}.add(new PQ(-1, 'mo')).asDate().getMonth()")
97
+ assert @context.eval("#{ts2}.before(#{ts})")
98
+ assert @context.eval("#{ts3}.after(#{ts})")
99
+ assert !@context.eval("#{ts}.before(#{ts2})")
100
+ assert !@context.eval("#{ts}.after(#{ts3})")
101
+ assert @context.eval("#{ts}.beforeOrConcurrent(#{ts})")
102
+ assert @context.eval("#{ts}.afterOrConcurrent(#{ts})")
103
+
104
+ # The following tests are taken from the Joint Commission guidance on time difference
105
+ # calculations
106
+
107
+ # Year difference calculation
108
+ ts1 = 'new TS("20120310220509")'
109
+ ts2 = 'new TS("20130218191003")'
110
+ assert_equal 0, @context.eval("#{ts1}.difference(#{ts2},'a')")
111
+
112
+ ts1 = 'new TS("20120310220509")'
113
+ ts2 = 'new TS("20130310080159")'
114
+ assert_equal 1, @context.eval("#{ts1}.difference(#{ts2},'a')")
115
+
116
+ ts1 = 'new TS("20120310220509")'
117
+ ts2 = 'new TS("20130320040130")'
118
+ assert_equal 1, @context.eval("#{ts1}.difference(#{ts2},'a')")
119
+
120
+ ts1 = 'new TS("20120229")'
121
+ ts2 = 'new TS("20140228")'
122
+ assert_equal 1, @context.eval("#{ts1}.difference(#{ts2},'a')")
123
+
124
+ ts1 = 'new TS("20120310111602")'
125
+ ts2 = 'new TS("20130815213416")'
126
+ assert_equal 1, @context.eval("#{ts1}.difference(#{ts2},'a')")
127
+
128
+ ts1 = 'new TS("20120229101856")'
129
+ ts2 = 'new TS("20140301190234")'
130
+ assert_equal 2, @context.eval("#{ts1}.difference(#{ts2},'a')")
131
+
132
+ # Month difference calculation
133
+ ts1 = 'new TS("20120301140545")'
134
+ ts2 = 'new TS("20120331230149")'
135
+ assert_equal 0, @context.eval("#{ts1}.difference(#{ts2},'mo')")
136
+
137
+ ts1 = 'new TS("20120310220509")'
138
+ ts2 = 'new TS("20130630130023")'
139
+ assert_equal 15, @context.eval("#{ts1}.difference(#{ts2},'mo')")
140
+
141
+ ts1 = 'new TS("20120310220509")'
142
+ ts2 = 'new TS("20130129071933")'
143
+ assert_equal 10, @context.eval("#{ts1}.difference(#{ts2},'mo')")
144
+
145
+ # Week difference calculation
146
+ ts1 = 'new TS("20120310220509")'
147
+ ts2 = 'new TS("20120320071933")'
148
+ assert_equal 1, @context.eval("#{ts1}.difference(#{ts2},'wk')")
149
+
150
+ # Day difference calculation
151
+ ts1 = 'new TS("20120131123000")'
152
+ ts2 = 'new TS("20120201090000")'
153
+ assert_equal 1, @context.eval("#{ts1}.difference(#{ts2},'d')")
154
+
155
+ ts1 = 'new TS("20120131123000")'
156
+ ts2 = 'new TS("20120201140000")'
157
+ assert_equal 1, @context.eval("#{ts1}.difference(#{ts2},'d')")
158
+
159
+ # Hour difference calculation
160
+ ts1 = 'new TS("201203010310")'
161
+ ts2 = 'new TS("201203010510")'
162
+ assert_equal 2, @context.eval("#{ts1}.difference(#{ts2},'h')")
163
+
164
+ ts1 = 'new TS("201202292310")'
165
+ ts2 = 'new TS("201203010010")'
166
+ assert_equal 1, @context.eval("#{ts1}.difference(#{ts2},'h')")
167
+
168
+ ts1 = 'new TS("201203010310")'
169
+ ts2 = 'new TS("201203010400")'
170
+ assert_equal 0, @context.eval("#{ts1}.difference(#{ts2},'h')")
171
+
172
+ # Minute difference calculation
173
+ ts1 = 'new TS("201203010310")'
174
+ ts2 = 'new TS("201203010520")'
175
+ assert_equal 130, @context.eval("#{ts1}.difference(#{ts2},'min')")
176
+
177
+ ts1 = 'new TS("201202292310")'
178
+ ts2 = 'new TS("201203010020")'
179
+ assert_equal 70, @context.eval("#{ts1}.difference(#{ts2},'min')")
180
+
181
+ # Additional tests from previous version of TJC guidance
182
+ ts4 = 'new TS("20000310")'
183
+ ts5 = 'new TS("20110405")'
184
+ ts6 = 'new TS("20000229")'
185
+ ts7 = 'new TS("20110228")'
186
+ ts8 = 'new TS("20120228")'
187
+ assert_equal 11, @context.eval("#{ts4}.difference(#{ts5},'a')")
188
+ assert_equal 11, @context.eval("#{ts5}.difference(#{ts4},'a')")
189
+ assert_equal 10, @context.eval("#{ts6}.difference(#{ts7},'a')")
190
+ assert_equal 10, @context.eval("#{ts7}.difference(#{ts6},'a')")
191
+ assert_equal 1, @context.eval("#{ts7}.difference(#{ts8},'a')")
192
+ assert_equal 1, @context.eval("#{ts8}.difference(#{ts7},'a')")
193
+ ts9 = 'new TS("20000229")'
194
+ ts10 = 'new TS("20010330")'
195
+ ts11 = 'new TS("20101228")'
196
+ ts12 = 'new TS("20110217")'
197
+ ts13 = 'new TS("20080320")'
198
+ ts14 = 'new TS("20080401")'
199
+ assert_equal 13, @context.eval("#{ts9}.difference(#{ts10},'mo')")
200
+ assert_equal 1, @context.eval("#{ts11}.difference(#{ts12},'mo')")
201
+ assert_equal 0, @context.eval("#{ts13}.difference(#{ts14},'mo')")
202
+ ts15 = 'new TS("201203010310")'
203
+ ts16 = 'new TS("201203010520")'
204
+ ts17 = 'new TS("201202292310")'
205
+ ts18 = 'new TS("201203010020")'
206
+ assert_equal 130, @context.eval("#{ts15}.difference(#{ts16},'min')")
207
+ assert_equal 70, @context.eval("#{ts17}.difference(#{ts18},'min')")
208
+ ts19 = 'new TS("201203010310")'
209
+ ts20 = 'new TS("201203010520")'
210
+ ts21 = 'new TS("201202292310")'
211
+ ts22 = 'new TS("201203010010")'
212
+ ts23 = 'new TS("201203010310")'
213
+ ts24 = 'new TS("201203010400")'
214
+ assert_equal 2, @context.eval("#{ts19}.difference(#{ts20},'h')")
215
+ assert_equal 1, @context.eval("#{ts21}.difference(#{ts22},'h')")
216
+ assert_equal 0, @context.eval("#{ts23}.difference(#{ts24},'h')")
217
+ ts25 = 'new TS("200002280900")'
218
+ ts26 = 'new TS("200002292359")'
219
+ ts27 = 'new TS("200012282300")'
220
+ ts28 = 'new TS("200101010800")'
221
+ ts29 = 'new TS("200002280900")'
222
+ ts30 = 'new TS("200002282359")'
223
+ assert_equal 1, @context.eval("#{ts25}.difference(#{ts26},'d')")
224
+ assert_equal 4, @context.eval("#{ts27}.difference(#{ts28},'d')")
225
+ assert_equal 0, @context.eval("#{ts29}.difference(#{ts30},'d')")
226
+ ts31 = 'new TS("20120403")'
227
+ ts32 = 'new TS("20120410")'
228
+ ts33 = 'new TS("20120229")'
229
+ ts34 = 'new TS("20120328")'
230
+ assert_equal 0, @context.eval("#{ts31}.difference(#{ts31},'wk')")
231
+ assert_equal 1, @context.eval("#{ts31}.difference(#{ts32},'wk')")
232
+ assert_equal 4, @context.eval("#{ts33}.difference(#{ts34},'wk')")
233
+ end
234
+
235
+ def test_cd
236
+ # CD - Code
237
+ cd = "new CD('M')"
238
+ assert_equal 'M', @context.eval("#{cd}.code")
239
+ assert @context.eval("#{cd}.match('M')")
240
+ assert !@context.eval("#{cd}.match('F')")
241
+ end
242
+
243
+ def test_iv_pq
244
+ # IVL_PQ - Range
245
+ ivl = "new IVL_PQ(new PQ(1, 'mo'), new PQ(10, 'mo'))"
246
+ assert_equal 1, @context.eval("#{ivl}.low_pq.value")
247
+ assert_equal 10, @context.eval("#{ivl}.high_pq.value")
248
+ assert @context.eval("#{ivl}.match(5)")
249
+ assert !@context.eval("#{ivl}.match(0)")
250
+ assert !@context.eval("#{ivl}.match(11)")
251
+ # IVL with null values on the ends
252
+ assert @context.eval("new IVL_PQ(null, new PQ(10, 'mo')).match(5)")
253
+ assert !@context.eval("new IVL_PQ(null, new PQ(10, 'mo')).match(11)")
254
+ assert @context.eval("new IVL_PQ(new PQ(1, 'mo'), null).match(2)")
255
+ assert !@context.eval("new IVL_PQ(new PQ(1, 'mo'), null).match(0)")
256
+ end
257
+
258
+ def test_ivl_ts
259
+ # IVL_TS - Time Range
260
+ ivl1 = 'new IVL_TS(new TS("20120310"), new TS("20120320"))'
261
+ ivl2 = 'new IVL_TS(new TS("20120312"), new TS("20120320"))'
262
+ assert @context.eval("#{ivl2}.DURING(#{ivl1})")
263
+ assert_equal 2010, @context.eval('getIVL(new Date(2010,1,1)).low.asDate().getFullYear()')
264
+ end
265
+
266
+ def test_any_non_null
267
+ # ANYNonNull
268
+ ann = 'new ANYNonNull()'
269
+ assert @context.eval("#{ann}.match('foo')")
270
+ assert @context.eval("#{ann}.match(10)")
271
+ assert @context.eval("#{ann}.match(0)")
272
+ assert @context.eval("#{ann}.match({'scalar': 10})")
273
+ assert @context.eval("#{ann}.match({'scalar': 0})")
274
+ assert !@context.eval("#{ann}.match(null)")
275
+ assert !@context.eval("#{ann}.match({'scalar': null})")
276
+ end
277
+
278
+ def test_matching_value
279
+ # Matching value
280
+ assert @context.eval("matchingValue(5, new IVL_PQ(PQ(3, 'mo'), new PQ(9, 'mo'))).isTrue()")
281
+ assert !@context.eval("matchingValue(12, new IVL_PQ(PQ(3, 'mo'), new PQ(9, 'mo'))).isTrue()")
282
+ end
283
+
284
+ def test_count
285
+ # COUNT
286
+ events0 = '[]'
287
+ events1 = '[1]'
288
+ events2 = '[1,2]'
289
+ exactly0 = 'new IVL_PQ(new PQ(0), new PQ(0))'
290
+ exactly1 = 'new IVL_PQ(new PQ(1), new PQ(1))'
291
+ moreThanZero = 'new IVL_PQ(new PQ(1))'
292
+ lessThanTwo = 'new IVL_PQ(null, new PQ(1))'
293
+ assert @context.eval("COUNT(#{events0}, #{exactly0}).isTrue()")
294
+ assert !@context.eval("COUNT(#{events0}, #{exactly1}).isTrue()")
295
+ assert !@context.eval("COUNT(#{events0}, #{moreThanZero}).isTrue()")
296
+ assert @context.eval("COUNT(#{events0}, #{lessThanTwo}).isTrue()")
297
+ assert !@context.eval("COUNT(#{events1}, #{exactly0}).isTrue()")
298
+ assert @context.eval("COUNT(#{events1}, #{exactly1}).isTrue()")
299
+ assert @context.eval("COUNT(#{events1}, #{moreThanZero}).isTrue()")
300
+ assert @context.eval("COUNT(#{events1}, #{lessThanTwo}).isTrue()")
301
+ assert !@context.eval("COUNT(#{events2}, #{exactly0}).isTrue()")
302
+ assert !@context.eval("COUNT(#{events2}, #{exactly1}).isTrue()")
303
+ assert @context.eval("COUNT(#{events2}, #{moreThanZero}).isTrue()")
304
+ assert !@context.eval("COUNT(#{events2}, #{lessThanTwo}).isTrue()")
305
+ end
306
+
307
+ def test_union
308
+ # UNION
309
+ events0 = '[]'
310
+ events1 = '[1]'
311
+ events2 = '[2,3]'
312
+ assert @context.eval("UNION().length===0")
313
+ assert @context.eval("UNION(#{events0}).length===0")
314
+ assert @context.eval("UNION(#{events1}).length===1")
315
+ assert @context.eval("UNION(#{events1},#{events2}).length===3")
316
+ assert @context.eval("UNION(#{events0},#{events2}).length===2")
317
+ end
318
+
319
+ def test_xproduct
320
+ # XPRODUCT
321
+ events0 = '[]'
322
+ events1 = '[1]'
323
+ events2 = '[2,3]'
324
+ assert_equal 0, @context.eval("XPRODUCT().length")
325
+ assert_equal 0, @context.eval("XPRODUCT(#{events0}).length")
326
+ assert_equal 1, @context.eval("XPRODUCT(#{events0}).eventLists.length")
327
+ assert_equal 1, @context.eval("XPRODUCT(#{events1}).length")
328
+ assert_equal 1, @context.eval("XPRODUCT(#{events1}).eventLists.length")
329
+ assert_equal 3, @context.eval("XPRODUCT(#{events1},#{events2}).length")
330
+ assert_equal 2, @context.eval("XPRODUCT(#{events1},#{events2}).eventLists.length")
331
+ assert_equal 2, @context.eval("XPRODUCT(#{events0},#{events2}).length")
332
+ assert_equal 2, @context.eval("XPRODUCT(#{events0},#{events2}).eventLists.length")
333
+ end
334
+
335
+ def test_temporal_operators
336
+ # Events and bounds for temporal operators
337
+ @context.eval('var events1 = [{"asIVL_TS": function() {return new IVL_TS(new TS("20120105"), new TS("20120105"));}}]')
338
+ @context.eval('var events2 = [{"asIVL_TS": function() {return new IVL_TS(new TS("20120102"), new TS("20120105"));}}]')
339
+ @context.eval('var bound1 = [{"asIVL_TS": function() {return new IVL_TS(new TS("20120105"), new TS("20120105"));}}]')
340
+ @context.eval('var bound2 = [{"asIVL_TS": function() {return new IVL_TS(new TS("20120107"), new TS("20120107"));}}]')
341
+ @context.eval('var bound3 = [{"asIVL_TS": function() {return new IVL_TS(new TS("20120103"), new TS("20120107"));}}]')
342
+ @context.eval('var bound4 = [{"asIVL_TS": function() {return new IVL_TS(new TS("20120106"), new TS("20120107"));}}]')
343
+ @context.eval('var bound5 = {"asIVL_TS": function() {return new IVL_TS(new TS("20120106"), new TS("20120107"));}}')
344
+ @context.eval('var nullStartBound = new IVL_TS(new TS("20120105"), new TS("20120105"));')
345
+ @context.eval('nullStartBound.low.date = null;')
346
+ @context.eval('var bound6 = {"asIVL_TS": function() {return nullStartBound;}}')
347
+ @context.eval('var range1 = new IVL_PQ(null, new PQ(1, "d"))')
348
+ @context.eval('var range2 = new IVL_PQ(new PQ(1, "d"), null)')
349
+
350
+ # DURING
351
+ assert_equal 1, @context.eval('DURING(events1, bound1)').count
352
+ assert_equal 0, @context.eval('DURING(events1, bound2)').count
353
+ assert_equal 1, @context.eval('DURING(events1, bound3)').count
354
+ assert_equal 0, @context.eval('DURING(events1, bound4)').count
355
+ assert_equal 0, @context.eval('DURING(events1, bound5)').count
356
+ assert_equal 0, @context.eval('DURING(events1, bound6)').count
357
+ assert_equal 0, @context.eval('DURING(events2, bound3)').count
358
+ assert_equal 0, @context.eval('DURING(events2, bound4)').count
359
+ assert_equal 0, @context.eval('DURING(events2, bound5)').count
360
+ assert_equal 0, @context.eval('DURING(events2, bound6)').count
361
+ assert_equal 0, @context.eval('DURING(events2, bound1)').count
362
+ assert_equal 0, @context.eval('DURING(events2, bound2)').count
363
+ assert_equal 1, @context.eval('DURING(events1, XPRODUCT(bound1))').count
364
+ assert_equal 0, @context.eval('DURING(events1, XPRODUCT(bound2))').count
365
+ assert_equal 0, @context.eval('DURING(events1, XPRODUCT(bound1, bound2))').count
366
+ assert_equal 1, @context.eval('DURING(events1, XPRODUCT(bound3))').count
367
+ assert_equal 1, @context.eval('DURING(events1, XPRODUCT(bound1, bound3))').count
368
+ assert_equal 0, @context.eval('DURING(events1, XPRODUCT(bound4))').count
369
+ assert_equal 0, @context.eval('DURING(events1, XPRODUCT(bound5))').count
370
+ assert_equal 0, @context.eval('DURING(events1, XPRODUCT(bound6))').count
371
+ assert_equal 0, @context.eval('DURING(events2, XPRODUCT(bound3))').count
372
+ assert_equal 0, @context.eval('DURING(events2, XPRODUCT(bound4))').count
373
+ assert_equal 0, @context.eval('DURING(events2, XPRODUCT(bound5))').count
374
+ assert_equal 0, @context.eval('DURING(events2, XPRODUCT(bound6))').count
375
+ assert_equal 0, @context.eval('DURING(events2, XPRODUCT(bound1))').count
376
+ assert_equal 0, @context.eval('DURING(events2, XPRODUCT(bound2))').count
377
+
378
+ # OVERLAP
379
+ assert_equal 1, @context.eval('OVERLAP(events1, bound1)').count
380
+ assert_equal 0, @context.eval('OVERLAP(events1, bound2)').count
381
+ assert_equal 1, @context.eval('OVERLAP(events1, bound3)').count
382
+ assert_equal 0, @context.eval('OVERLAP(events1, bound4)').count
383
+ assert_equal 0, @context.eval('OVERLAP(events1, bound5)').count
384
+ assert_equal 0, @context.eval('OVERLAP(events1, bound6)').count
385
+ assert_equal 1, @context.eval('OVERLAP(events2, bound3)').count
386
+ assert_equal 0, @context.eval('OVERLAP(events2, bound4)').count
387
+ assert_equal 0, @context.eval('OVERLAP(events2, bound5)').count
388
+ assert_equal 0, @context.eval('OVERLAP(events2, bound6)').count
389
+ assert_equal 1, @context.eval('OVERLAP(events2, bound1)').count
390
+ assert_equal 0, @context.eval('OVERLAP(events2, bound2)').count
391
+ assert_equal 1, @context.eval('OVERLAP(events1, XPRODUCT(bound1))').count
392
+ assert_equal 0, @context.eval('OVERLAP(events1, XPRODUCT(bound2))').count
393
+ assert_equal 0, @context.eval('OVERLAP(events1, XPRODUCT(bound1, bound2))').count
394
+ assert_equal 1, @context.eval('OVERLAP(events1, XPRODUCT(bound3))').count
395
+ assert_equal 1, @context.eval('OVERLAP(events1, XPRODUCT(bound1, bound3))').count
396
+ assert_equal 0, @context.eval('OVERLAP(events1, XPRODUCT(bound4))').count
397
+ assert_equal 0, @context.eval('OVERLAP(events1, XPRODUCT(bound5))').count
398
+ assert_equal 0, @context.eval('OVERLAP(events1, XPRODUCT(bound6))').count
399
+ assert_equal 1, @context.eval('OVERLAP(events2, XPRODUCT(bound3))').count
400
+ assert_equal 0, @context.eval('OVERLAP(events2, XPRODUCT(bound4))').count
401
+ assert_equal 0, @context.eval('OVERLAP(events2, XPRODUCT(bound5))').count
402
+ assert_equal 0, @context.eval('OVERLAP(events2, XPRODUCT(bound6))').count
403
+ assert_equal 1, @context.eval('OVERLAP(events2, XPRODUCT(bound1))').count
404
+ assert_equal 0, @context.eval('OVERLAP(events2, XPRODUCT(bound2))').count
405
+
406
+ # SBS
407
+ assert_equal 0, @context.eval('SBS(events1, bound1)').count
408
+ assert_equal 0, @context.eval('SBS(events2, bound1, range1)').count
409
+ assert_equal 1, @context.eval('SBS(events2, bound1)').count
410
+ assert_equal 1, @context.eval('SBS(events2, bound1, range2)').count
411
+
412
+ # SAS
413
+ assert_equal 0, @context.eval('SAS(events1, bound1)').count
414
+ assert_equal 0, @context.eval('SAS(events2, bound1, range1)').count
415
+ assert_equal 0, @context.eval('SAS(events2, bound1)').count
416
+ assert_equal 0, @context.eval('SAS(events2, bound1, range2)').count
417
+
418
+ # SBE
419
+ assert_equal 0, @context.eval('SBE(events1, bound1)').count
420
+ assert_equal 1, @context.eval('SBE(events1, bound2)').count
421
+
422
+ # SAE
423
+ assert_equal 0, @context.eval('SAE(events1, bound1)').count
424
+ assert_equal 1, @context.eval('SAE(bound2, events1)').count
425
+
426
+ # EBS
427
+ assert_equal 0, @context.eval('EBS(events1, bound1)').count
428
+ assert_equal 1, @context.eval('EBS(events1, bound2)').count
429
+
430
+ # EAS
431
+ assert_equal 0, @context.eval('EAS(events1, bound1)').count
432
+ assert_equal 1, @context.eval('EAS(events1, bound3)').count
433
+
434
+ # EBE
435
+ assert_equal 0, @context.eval('EBE(events1, bound1)').count
436
+ assert_equal 1, @context.eval('EBE(events1, bound2)').count
437
+
438
+ # EAE
439
+ assert_equal 0, @context.eval('EAE(events1, bound1)').count
440
+ assert_equal 1, @context.eval('EAE(bound3, events2)').count
441
+
442
+ # SDU
443
+ assert_equal 1, @context.eval('SDU(events1, bound1)').count
444
+ assert_equal 0, @context.eval('SDU(events1, bound2)').count
445
+
446
+ # EDU
447
+ assert_equal 1, @context.eval('EDU(events1, bound1)').count
448
+ assert_equal 0, @context.eval('EDU(events1, bound2)').count
449
+
450
+ # ECW
451
+ assert_equal 1, @context.eval('ECW(events1, bound1)').count
452
+ assert_equal 1, @context.eval('ECW(events1, bound6)').count
453
+ assert_equal 0, @context.eval('ECW(events1, bound2)').count
454
+
455
+ # SCW
456
+ assert_equal 1, @context.eval('SCW(events1, bound1)').count
457
+ assert_equal 0, @context.eval('SCW(events1, bound6)').count
458
+ assert_equal 0, @context.eval('SCW(events1, bound2)').count
459
+
460
+ # ECWS
461
+ assert_equal 1, @context.eval('ECWS(events1, bound1)').count
462
+ assert_equal 0, @context.eval('ECWS(events1, bound6)').count
463
+ assert_equal 0, @context.eval('ECWS(events1, bound2)').count
464
+
465
+ # SCWE
466
+ assert_equal 1, @context.eval('SCWE(events1, bound1)').count
467
+ assert_equal 1, @context.eval('SCWE(events1, bound6)').count
468
+ assert_equal 0, @context.eval('SCWE(events1, bound2)').count
469
+
470
+ # CONCURRENT
471
+ assert_equal 1, @context.eval('CONCURRENT(events1, bound1)').count
472
+ assert_equal 0, @context.eval('CONCURRENT(events1, bound2)').count
473
+ end
474
+
475
+ def test_ordinal_operators
476
+ # Ordinal operators
477
+ ts20100101 = '{"timeStamp": function() {return new Date(2010,0,1);}}'
478
+ ts20100201 = '{"timeStamp": function() {return new Date(2010,1,1);}}'
479
+ ts20100301 = '{"timeStamp": function() {return new Date(2010,2,1);}}'
480
+ ts20100401 = '{"timeStamp": function() {return new Date(2010,3,1);}}'
481
+ ts20100501 = '{"timeStamp": function() {return new Date(2010,4,1);}}'
482
+ events0 = "[]"
483
+ events1 = "[#{ts20100101}]"
484
+ events2 = "[#{ts20100101},#{ts20100201}]"
485
+ events3 = "[#{ts20100101},#{ts20100201},#{ts20100301}]"
486
+ events4 = "[#{ts20100101},#{ts20100201},#{ts20100301},#{ts20100401}]"
487
+ events5 = "[#{ts20100101},#{ts20100201},#{ts20100301},#{ts20100401},#{ts20100501}]"
488
+ events6 = "[#{ts20100501},#{ts20100401},#{ts20100301},#{ts20100201},#{ts20100101}]"
489
+
490
+ assert_equal 0, @context.eval("RECENT(#{events0})").count
491
+ assert_equal 0, @context.eval("LAST(#{events0})").count
492
+ assert_equal 0, @context.eval("FIRST(#{events0})").count
493
+ assert_equal 0, @context.eval("SECOND(#{events1})").count
494
+ assert_equal 0, @context.eval("THIRD(#{events2})").count
495
+ assert_equal 0, @context.eval("FOURTH(#{events3})").count
496
+ assert_equal 0, @context.eval("FIFTH(#{events4})").count
497
+
498
+ assert_equal 1, @context.eval("RECENT(#{events1})").count
499
+ assert_equal 1, @context.eval("LAST(#{events1})").count
500
+ assert_equal 1, @context.eval("FIRST(#{events1})").count
501
+ assert_equal 1, @context.eval("SECOND(#{events2})").count
502
+ assert_equal 1, @context.eval("THIRD(#{events3})").count
503
+ assert_equal 1, @context.eval("FOURTH(#{events4})").count
504
+ assert_equal 1, @context.eval("FIFTH(#{events5})").count
505
+
506
+ assert_equal 1, @context.eval("LAST(#{events6})").count
507
+ assert_equal 4, @context.eval("LAST(#{events6})[0].timeStamp().getMonth()")
508
+ assert_equal 1, @context.eval("RECENT(#{events6})").count
509
+ assert_equal 4, @context.eval("RECENT(#{events6})[0].timeStamp().getMonth()")
510
+ assert_equal 1, @context.eval("FIRST(#{events6})").count
511
+ assert_equal 0, @context.eval("FIRST(#{events6})[0].timeStamp().getMonth()")
512
+ assert_equal 1, @context.eval("SECOND(#{events6})").count
513
+ assert_equal 1, @context.eval("SECOND(#{events6})[0].timeStamp().getMonth()")
514
+ assert_equal 1, @context.eval("THIRD(#{events6})").count
515
+ assert_equal 2, @context.eval("THIRD(#{events6})[0].timeStamp().getMonth()")
516
+ assert_equal 1, @context.eval("FOURTH(#{events6})").count
517
+ assert_equal 3, @context.eval("FOURTH(#{events6})[0].timeStamp().getMonth()")
518
+ assert_equal 1, @context.eval("FIFTH(#{events6})").count
519
+ assert_equal 4, @context.eval("FIFTH(#{events6})[0].timeStamp().getMonth()")
520
+ end
521
+
522
+ def test_summary_operators
523
+ # MIN and MAX
524
+ v10 = '{"value": function() {return {"scalar": 10};}}'
525
+ v20 = '{"value": function() {return {"scalar": 20};}}'
526
+ events0 = "[]"
527
+ events2 = "[#{v10},#{v20}]"
528
+ exactly10 = 'new IVL_PQ(new PQ(10), new PQ(10))'
529
+ exactly20 = 'new IVL_PQ(new PQ(20), new PQ(20))'
530
+ moreThan10 = 'new IVL_PQ(new PQ(11))'
531
+ lessThan20 = 'new IVL_PQ(null, new PQ(19))'
532
+ between15and25 = 'new IVL_PQ(new PQ(15), new PQ(25))'
533
+ assert !@context.eval("MIN(#{events0},#{exactly10}).isTrue()")
534
+ assert !@context.eval("MAX(#{events0},#{exactly10}).isTrue()")
535
+ assert !@context.eval("MIN(#{events0},#{exactly20}).isTrue()")
536
+ assert !@context.eval("MAX(#{events0},#{exactly20}).isTrue()")
537
+ assert @context.eval("MIN(#{events2},#{exactly10}).isTrue()")
538
+ assert !@context.eval("MAX(#{events2},#{exactly10}).isTrue()")
539
+ assert !@context.eval("MIN(#{events2},#{exactly20}).isTrue()")
540
+ assert @context.eval("MAX(#{events2},#{exactly20}).isTrue()")
541
+ assert !@context.eval("MIN(#{events2},#{moreThan10}).isTrue()")
542
+ assert @context.eval("MAX(#{events2},#{moreThan10}).isTrue()")
543
+ assert @context.eval("MIN(#{events2},#{lessThan20}).isTrue()")
544
+ assert !@context.eval("MAX(#{events2},#{lessThan20}).isTrue()")
545
+ assert !@context.eval("MIN(#{events2},#{between15and25}).isTrue()")
546
+ assert @context.eval("MAX(#{events2},#{between15and25}).isTrue()")
547
+ end
548
+
549
+ def test_respond_to
550
+ assert @context.eval("(new hQuery.Allergy({})).respondTo('severity')")
551
+ assert !@context.eval("(new hQuery.Allergy({})).respondTo('canHasCheeseburger')")
552
+ end
553
+ end