hqmf2js 1.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 (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