ncs_mdes 0.11.0 → 0.12.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.
- data/CHANGELOG.md +16 -0
- data/Gemfile +1 -1
- data/README.md +15 -5
- data/bin/mdes-console +3 -1
- data/documents/1.2/child_or_parent_instrument_tables.yml +28 -0
- data/documents/2.0/child_or_parent_instrument_tables.yml +68 -0
- data/documents/2.1/child_or_parent_instrument_tables.yml +74 -0
- data/documents/2.2/child_or_parent_instrument_tables.yml +98 -0
- data/documents/3.0/child_or_parent_instrument_tables.yml +119 -0
- data/documents/3.1/child_or_parent_instrument_tables.yml +187 -0
- data/documents/3.2/child_or_parent_instrument_tables.yml +192 -0
- data/documents/scan_p_ids_for_children.rb +39 -0
- data/lib/ncs_navigator/mdes/code_list.rb +94 -0
- data/lib/ncs_navigator/mdes/differences/collection.rb +47 -0
- data/lib/ncs_navigator/mdes/differences/collection_criterion.rb +59 -0
- data/lib/ncs_navigator/mdes/differences/entry.rb +48 -0
- data/lib/ncs_navigator/mdes/differences/value.rb +7 -0
- data/lib/ncs_navigator/mdes/differences/value_criterion.rb +58 -0
- data/lib/ncs_navigator/mdes/differences.rb +12 -0
- data/lib/ncs_navigator/mdes/source_documents.rb +27 -0
- data/lib/ncs_navigator/mdes/specification.rb +45 -0
- data/lib/ncs_navigator/mdes/transmission_table.rb +61 -0
- data/lib/ncs_navigator/mdes/variable.rb +58 -4
- data/lib/ncs_navigator/mdes/variable_type.rb +27 -62
- data/lib/ncs_navigator/mdes/version.rb +1 -1
- data/lib/ncs_navigator/mdes.rb +5 -1
- data/spec/differences_matchers.rb +40 -0
- data/spec/ncs_navigator/mdes/code_list_spec.rb +178 -0
- data/spec/ncs_navigator/mdes/source_documents_spec.rb +14 -0
- data/spec/ncs_navigator/mdes/specification_spec.rb +30 -0
- data/spec/ncs_navigator/mdes/transmission_table_spec.rb +77 -0
- data/spec/ncs_navigator/mdes/variable_spec.rb +244 -0
- data/spec/ncs_navigator/mdes/variable_type_spec.rb +161 -40
- data/spec/spec_helper.rb +6 -0
- metadata +24 -5
@@ -29,10 +29,19 @@ module NcsNavigator::Mdes
|
|
29
29
|
# table.)
|
30
30
|
attr_accessor :variables
|
31
31
|
|
32
|
+
##
|
33
|
+
# @see #child_instrument_table?
|
34
|
+
# @return [void]
|
35
|
+
attr_writer :child_instrument_table
|
36
|
+
|
32
37
|
def initialize(name)
|
33
38
|
@name = name
|
34
39
|
end
|
35
40
|
|
41
|
+
def variables
|
42
|
+
@variables ||= []
|
43
|
+
end
|
44
|
+
|
36
45
|
##
|
37
46
|
# Search for a variable by name.
|
38
47
|
#
|
@@ -110,5 +119,57 @@ module NcsNavigator::Mdes
|
|
110
119
|
def operational_table?
|
111
120
|
!instrument_table?
|
112
121
|
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Is this a child instrument data table? (As opposed to a parent instrument
|
125
|
+
# data table or neither.)
|
126
|
+
#
|
127
|
+
# This reports the type of participant whose p_id should go in this table's
|
128
|
+
# p_id variable.
|
129
|
+
#
|
130
|
+
# Return values:
|
131
|
+
#
|
132
|
+
# * `true`: The p_id should be a child's p_id.
|
133
|
+
# * `false`: The p_id should be a parent's p_id.
|
134
|
+
# * `nil`: The table isn't an instrument data table, or it doesn't have a p_id
|
135
|
+
# variable, or the childness of the p_id isn't known.
|
136
|
+
#
|
137
|
+
# @return [true,false,nil]
|
138
|
+
def child_instrument_table?
|
139
|
+
@child_instrument_table
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# Is this a parent instrument data table? (As opposed to a child instrument
|
144
|
+
# data table or neither.)
|
145
|
+
#
|
146
|
+
# This reports the type of participant whose p_id should go in this table's
|
147
|
+
# p_id variable.
|
148
|
+
#
|
149
|
+
# Return values:
|
150
|
+
#
|
151
|
+
# * `true`: The p_id should be a parent's p_id.
|
152
|
+
# * `false`: The p_id should be a child's p_id.
|
153
|
+
# * `nil`: The table isn't an instrument data table, or it doesn't have a p_id
|
154
|
+
# variable, or the childness of the p_id isn't known.
|
155
|
+
#
|
156
|
+
# @return [true,false,nil]
|
157
|
+
def parent_instrument_table?
|
158
|
+
child_instrument_table?.nil? ? nil : !child_instrument_table?
|
159
|
+
end
|
160
|
+
|
161
|
+
# @private
|
162
|
+
DIFF_CRITERIA = {
|
163
|
+
:name => Differences::ValueCriterion.new,
|
164
|
+
:variables => Differences::CollectionCriterion.new(:name)
|
165
|
+
}
|
166
|
+
|
167
|
+
##
|
168
|
+
# Computes the differences between this table and the other.
|
169
|
+
#
|
170
|
+
# @return [Differences::Entry,nil]
|
171
|
+
def diff(other_table, options={})
|
172
|
+
Differences::Entry.compute(self, other_table, DIFF_CRITERIA, options)
|
173
|
+
end
|
113
174
|
end
|
114
175
|
end
|
@@ -111,10 +111,6 @@ module NcsNavigator::Mdes
|
|
111
111
|
@name = name
|
112
112
|
end
|
113
113
|
|
114
|
-
def constraints
|
115
|
-
@constraints ||= []
|
116
|
-
end
|
117
|
-
|
118
114
|
##
|
119
115
|
# Is a value for the variable mandatory for a valid submission?
|
120
116
|
#
|
@@ -205,5 +201,63 @@ module NcsNavigator::Mdes
|
|
205
201
|
end
|
206
202
|
end
|
207
203
|
end
|
204
|
+
|
205
|
+
# @private
|
206
|
+
class EmbeddedVariableTypeCriterion
|
207
|
+
def apply(vt1, vt2, diff_options)
|
208
|
+
cvt1 = vt1 || VariableType.new
|
209
|
+
cvt2 = vt2 || VariableType.new
|
210
|
+
|
211
|
+
|
212
|
+
if cvt1.name && cvt2.name && cvt1.name == cvt2.name
|
213
|
+
# If they are named and have the same name, the differences will
|
214
|
+
# be reported once under the specification's entry for the named type.
|
215
|
+
nil
|
216
|
+
else
|
217
|
+
cvt1.diff(cvt2, diff_options)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def diff_criteria(diff_options={})
|
223
|
+
base = {
|
224
|
+
:name => Differences::ValueCriterion.new,
|
225
|
+
:type => EmbeddedVariableTypeCriterion.new,
|
226
|
+
:pii => Differences::ValueCriterion.new,
|
227
|
+
:omittable? => Differences::ValueCriterion.new(:comparator => :predicate),
|
228
|
+
:nillable? => Differences::ValueCriterion.new(:comparator => :predicate),
|
229
|
+
:table_reference => Differences::ValueCriterion.new(
|
230
|
+
:value_extractor => lambda { |o| o ? o.name : nil }
|
231
|
+
)
|
232
|
+
}
|
233
|
+
|
234
|
+
if diff_options[:strict]
|
235
|
+
base[:status] = Differences::ValueCriterion.new
|
236
|
+
else
|
237
|
+
base[:status] = Differences::ValueCriterion.new(
|
238
|
+
:comparator => lambda { |left, right|
|
239
|
+
no_change_changes = [
|
240
|
+
[:new, :active],
|
241
|
+
[:new, :modified],
|
242
|
+
[:active, :modified],
|
243
|
+
[:modified, :active]
|
244
|
+
]
|
245
|
+
|
246
|
+
no_change_changes.include?([left, right]) || (left == right)
|
247
|
+
}
|
248
|
+
)
|
249
|
+
end
|
250
|
+
|
251
|
+
base
|
252
|
+
end
|
253
|
+
protected :diff_criteria
|
254
|
+
|
255
|
+
##
|
256
|
+
# Computes the differences between this variable and the other.
|
257
|
+
#
|
258
|
+
# @return [Differences::Entry,nil]
|
259
|
+
def diff(other_variable, options={})
|
260
|
+
Differences::Entry.compute(self, other_variable, diff_criteria(options), options)
|
261
|
+
end
|
208
262
|
end
|
209
263
|
end
|
@@ -127,70 +127,35 @@ module NcsNavigator::Mdes
|
|
127
127
|
"#<#{self.class} #{attrs.join(' ')}>"
|
128
128
|
end
|
129
129
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
attr_accessor :label
|
154
|
-
|
155
|
-
##
|
156
|
-
# @return [String] the MDES's globally-unique identifier for
|
157
|
-
# this coded value.
|
158
|
-
attr_accessor :global_value
|
159
|
-
|
160
|
-
##
|
161
|
-
# @return [String] the name of MDES's master code list from
|
162
|
-
# which this value is derived.
|
163
|
-
attr_accessor :master_cl
|
164
|
-
|
165
|
-
class << self
|
166
|
-
##
|
167
|
-
# Creates a new instance from a `xs:enumeration` simple type
|
168
|
-
# restriction subelement.
|
169
|
-
#
|
170
|
-
# @param [Nokogiri::XML::Element] enum the `xs:enumeration`
|
171
|
-
# element.
|
172
|
-
# @param [Hash] options
|
173
|
-
# @option options [#warn] :log the logger to which to direct warnings
|
174
|
-
#
|
175
|
-
# @return [CodeListEntry]
|
176
|
-
def from_xsd_enumeration(enum, options={})
|
177
|
-
log = options[:log] || NcsNavigator::Mdes.default_logger
|
178
|
-
|
179
|
-
log.warn("Missing value for code list entry on line #{enum.line}") unless enum['value']
|
180
|
-
|
181
|
-
new(enum['value'] && enum['value'].strip).tap do |cle|
|
182
|
-
cle.label = enum['ncsdoc:label']
|
183
|
-
cle.global_value = enum['ncsdoc:global_value']
|
184
|
-
cle.master_cl = enum['ncsdoc:master_cl']
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
def initialize(value)
|
190
|
-
@value = value
|
130
|
+
def diff_criteria(diff_options={})
|
131
|
+
base = {
|
132
|
+
:name => Differences::ValueCriterion.new,
|
133
|
+
:base_type => Differences::ValueCriterion.new,
|
134
|
+
:pattern => Differences::ValueCriterion.new,
|
135
|
+
:max_length => Differences::ValueCriterion.new,
|
136
|
+
:min_length => Differences::ValueCriterion.new,
|
137
|
+
}
|
138
|
+
|
139
|
+
if diff_options[:strict]
|
140
|
+
base.merge(
|
141
|
+
:code_list_by_value => Differences::CollectionCriterion.new(
|
142
|
+
:value, :collection => :code_list),
|
143
|
+
:code_list_by_label => Differences::CollectionCriterion.new(
|
144
|
+
:label, :collection => :code_list)
|
145
|
+
)
|
146
|
+
else
|
147
|
+
base.merge(
|
148
|
+
:code_list_by_value => Differences::CollectionCriterion.new(
|
149
|
+
:value, :collection => :code_list),
|
150
|
+
:code_list_by_label => Differences::CollectionCriterion.new(
|
151
|
+
:label, :collection => :code_list, :value_extractor => :word_chars_downcase)
|
152
|
+
)
|
191
153
|
end
|
154
|
+
end
|
155
|
+
protected :diff_criteria
|
192
156
|
|
193
|
-
|
157
|
+
def diff(other_type, options={})
|
158
|
+
Differences::Entry.compute(self, other_type, diff_criteria(options), options)
|
194
159
|
end
|
195
160
|
end
|
196
161
|
end
|
data/lib/ncs_navigator/mdes.rb
CHANGED
@@ -4,6 +4,8 @@ module NcsNavigator
|
|
4
4
|
module Mdes
|
5
5
|
autoload :VERSION, 'ncs_navigator/mdes/version'
|
6
6
|
|
7
|
+
autoload :CodeList, 'ncs_navigator/mdes/code_list'
|
8
|
+
autoload :CodeListEntry, 'ncs_navigator/mdes/code_list'
|
7
9
|
autoload :SourceDocuments, 'ncs_navigator/mdes/source_documents'
|
8
10
|
autoload :Specification, 'ncs_navigator/mdes/specification'
|
9
11
|
autoload :TransmissionTable, 'ncs_navigator/mdes/transmission_table'
|
@@ -12,6 +14,8 @@ module NcsNavigator
|
|
12
14
|
|
13
15
|
autoload :DispositionCode, 'ncs_navigator/mdes/disposition_code'
|
14
16
|
|
17
|
+
autoload :Differences, 'ncs_navigator/mdes/differences'
|
18
|
+
|
15
19
|
##
|
16
20
|
# @return the default logger for this module when no other one is
|
17
21
|
# specified. It logs to standard error.
|
@@ -22,7 +26,7 @@ module NcsNavigator
|
|
22
26
|
|
23
27
|
##
|
24
28
|
# @return [Mdes::Specification] a new {Mdes::Specification} for the given
|
25
|
-
# version. See {Specification#initialize} for accepted options.
|
29
|
+
# version. See {Mdes::Specification#initialize} for accepted options.
|
26
30
|
def self.Mdes(version, options={})
|
27
31
|
Mdes::Specification.new(version, options)
|
28
32
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rspec/expectations'
|
2
|
+
|
3
|
+
module NcsNavigator::Mdes::Spec::Matchers
|
4
|
+
class ValueDiffMatcher
|
5
|
+
attr_reader :left, :right, :actual
|
6
|
+
|
7
|
+
def initialize(left, right)
|
8
|
+
@left = left
|
9
|
+
@right = right
|
10
|
+
end
|
11
|
+
|
12
|
+
def left_matches?(actual)
|
13
|
+
left == actual.left
|
14
|
+
end
|
15
|
+
|
16
|
+
def right_matches?(actual)
|
17
|
+
right == actual.right
|
18
|
+
end
|
19
|
+
|
20
|
+
def matches?(actual)
|
21
|
+
@actual = actual
|
22
|
+
actual && left_matches?(actual) && right_matches?(actual)
|
23
|
+
end
|
24
|
+
|
25
|
+
def failure_message_for_should
|
26
|
+
if (!actual)
|
27
|
+
"expected a difference but got none"
|
28
|
+
else
|
29
|
+
[
|
30
|
+
("expected left=#{left.inspect} but was #{actual.left.inspect}" unless left_matches?(actual)),
|
31
|
+
("expected right=#{right.inspect} but was #{actual.right.inspect}" unless right_matches?(actual))
|
32
|
+
].compact.join(' and ')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def be_a_value_diff(left, right)
|
38
|
+
ValueDiffMatcher.new(left, right)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module NcsNavigator::Mdes
|
6
|
+
describe CodeListEntry do
|
7
|
+
describe '.from_xsd_enumeration' do
|
8
|
+
def code_list_entry(xml_s)
|
9
|
+
CodeListEntry.from_xsd_enumeration(schema_element(xml_s), :log => logger)
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:missing) {
|
13
|
+
code_list_entry(<<-XSD)
|
14
|
+
<xs:enumeration value="-4" ncsdoc:label="Missing in Error" ncsdoc:desc="" ncsdoc:global_value="99-4" ncsdoc:master_cl="missing_data"/>
|
15
|
+
XSD
|
16
|
+
}
|
17
|
+
|
18
|
+
describe '#value' do
|
19
|
+
it 'is set' do
|
20
|
+
missing.value.should == "-4"
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'warns when missing' do
|
24
|
+
code_list_entry('<xs:enumeration ncsdoc:label="Foo"/>')
|
25
|
+
logger[:warn].first.should == 'Missing value for code list entry on line 2'
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'with external whitespace on the value' do
|
29
|
+
let(:missing) {
|
30
|
+
code_list_entry(<<-XSD)
|
31
|
+
<xs:enumeration value=" -4 " ncsdoc:label="Missing in Error" ncsdoc:desc="" ncsdoc:global_value="99-4" ncsdoc:master_cl="missing_data"/>
|
32
|
+
XSD
|
33
|
+
}
|
34
|
+
|
35
|
+
it 'removes the whitespace' do
|
36
|
+
missing.value.should == '-4'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#label" do
|
42
|
+
it 'is set' do
|
43
|
+
missing.label.should == "Missing in Error"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#global_value' do
|
48
|
+
it 'is set' do
|
49
|
+
missing.global_value.should == '99-4'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#master_cl' do
|
54
|
+
it 'is set' do
|
55
|
+
missing.master_cl.should == 'missing_data'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#to_s' do
|
61
|
+
it 'is the value' do
|
62
|
+
CodeListEntry.new('14').to_s.should == '14'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#diff' do
|
67
|
+
let(:a) { CodeListEntry.new('A') }
|
68
|
+
let(:aprime) { CodeListEntry.new('A') }
|
69
|
+
|
70
|
+
let(:diff) { a.diff(aprime) }
|
71
|
+
let(:strict_diff) { a.diff(aprime, :strict => true) }
|
72
|
+
|
73
|
+
it 'reports nothing for no differences' do
|
74
|
+
diff.should be_nil
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'value' do
|
78
|
+
let(:b) { CodeListEntry.new('B') }
|
79
|
+
|
80
|
+
it 'reports a difference' do
|
81
|
+
b.diff(a)[:value].should be_a_value_diff('B', 'A')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe 'label' do
|
86
|
+
describe 'with a text difference' do
|
87
|
+
before do
|
88
|
+
a.label = 'Aleph'
|
89
|
+
aprime.label = 'Alpha'
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'when not strict, it reports the normalized difference' do
|
93
|
+
diff[:label].should be_a_value_diff('aleph', 'alpha')
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'when strict, it reports the literal difference' do
|
97
|
+
strict_diff[:label].should be_a_value_diff('Aleph', 'Alpha')
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe 'with a whitespace-only difference' do
|
102
|
+
before do
|
103
|
+
a.label = " a\t\tb "
|
104
|
+
aprime.label = 'a b'
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'reports a difference in strict mode' do
|
108
|
+
strict_diff[:label].should be_a_value_diff(a.label, aprime.label)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'does not report a difference when not strict' do
|
112
|
+
diff.should be_nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe 'with a case-only difference' do
|
117
|
+
before do
|
118
|
+
a.label = 'AbcdEf'
|
119
|
+
aprime.label = 'aBCDeF'
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'reports a difference in strict mode' do
|
123
|
+
strict_diff[:label].should be_a_value_diff(a.label, aprime.label)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'does not report a difference when not strict' do
|
127
|
+
diff.should be_nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe 'with a punctuation-only difference' do
|
132
|
+
before do
|
133
|
+
a.label = 'a,b,|c[at+]-'
|
134
|
+
aprime.label = 'a!b*&c$#at'
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'reports a difference in strict mode' do
|
138
|
+
strict_diff[:label].should be_a_value_diff(a.label, aprime.label)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'does not report a difference when not strict' do
|
142
|
+
diff.should be_nil
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe 'global_value' do
|
148
|
+
before do
|
149
|
+
a.global_value = '0'
|
150
|
+
aprime.global_value = '-0'
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'reports a difference in strict mode' do
|
154
|
+
strict_diff[:global_value].should be_a_value_diff('0', '-0')
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'does not report a difference otherwise' do
|
158
|
+
diff.should be_nil
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe 'master_cl' do
|
163
|
+
before do
|
164
|
+
a.master_cl = 'C'
|
165
|
+
aprime.master_cl = 'Cprime'
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'reports a difference in strict mode' do
|
169
|
+
strict_diff[:master_cl].should be_a_value_diff('C', 'Cprime')
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'does not report a difference otherwise' do
|
173
|
+
diff.should be_nil
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -71,6 +71,16 @@ module NcsNavigator::Mdes
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
describe '#child_or_parent_instrument_tables' do
|
75
|
+
let(:property) { :child_or_parent_instrument_tables }
|
76
|
+
|
77
|
+
it_behaves_like 'an absolutizing path accessor'
|
78
|
+
|
79
|
+
it 'is optional' do
|
80
|
+
SourceDocuments.new.child_or_parent_instrument_tables.should be_nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
74
84
|
describe '.get' do
|
75
85
|
shared_examples 'version docs' do
|
76
86
|
subject { SourceDocuments.get(version) }
|
@@ -83,6 +93,10 @@ module NcsNavigator::Mdes
|
|
83
93
|
subject.disposition_codes.should =~ %r{#{version}/disposition_codes.yml$}
|
84
94
|
end
|
85
95
|
|
96
|
+
it 'has the correct path for the parent-child instrument tables list' do
|
97
|
+
subject.child_or_parent_instrument_tables.should =~ %r{#{version}/child_or_parent_instrument_tables.yml$}
|
98
|
+
end
|
99
|
+
|
86
100
|
it 'is of the specified version' do
|
87
101
|
subject.version.should == version
|
88
102
|
end
|
@@ -53,6 +53,18 @@ module NcsNavigator::Mdes
|
|
53
53
|
lambda { table.instrument_table? }.should_not raise_error
|
54
54
|
end
|
55
55
|
end
|
56
|
+
|
57
|
+
it 'knows the mother-childness of all p_id-bearing instrument tables' do
|
58
|
+
p_id_instrument_tables = tables.select { |t| t.instrument_table? && t.variables.collect(&:name).include?('p_id') }
|
59
|
+
p_id_instrument_tables.
|
60
|
+
reject { |t| [true, false].include?(t.child_instrument_table?) }.
|
61
|
+
collect { |t| t.name }.should == []
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'has some child and some parent instrument data tables' do
|
65
|
+
index = tables.each_with_object(Hash.new(0)) { |t, acc| acc[t.child_instrument_table?] += 1 }
|
66
|
+
index.keys.sort_by { |k| k.inspect }.should == [false, nil, true]
|
67
|
+
end
|
56
68
|
end
|
57
69
|
|
58
70
|
context 'in version 1.2' do
|
@@ -275,5 +287,23 @@ module NcsNavigator::Mdes
|
|
275
287
|
include_examples 'types fully resolved'
|
276
288
|
end
|
277
289
|
end
|
290
|
+
|
291
|
+
describe '#diff' do
|
292
|
+
let(:diff) {
|
293
|
+
Specification.new('2.0').diff(Specification.new('2.1'))
|
294
|
+
}
|
295
|
+
|
296
|
+
it 'finds different spec versions' do
|
297
|
+
diff[:specification_version].should be_a_value_diff('2.0.01.02', '2.1.00.00')
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'finds different tables' do
|
301
|
+
diff[:transmission_tables].right_only.should include('preg_visit_1_saq_3')
|
302
|
+
end
|
303
|
+
|
304
|
+
it 'finds different types' do
|
305
|
+
diff[:types].right_only.should include('person_partcpnt_reltnshp_cl5')
|
306
|
+
end
|
307
|
+
end
|
278
308
|
end
|
279
309
|
end
|
@@ -179,5 +179,82 @@ XSD
|
|
179
179
|
end
|
180
180
|
end
|
181
181
|
end
|
182
|
+
|
183
|
+
describe 'parent or child instrument table accessors' do
|
184
|
+
let(:t) { TransmissionTable.new('T') }
|
185
|
+
|
186
|
+
it 'is not a parent table when it is a child table' do
|
187
|
+
t.child_instrument_table = true
|
188
|
+
t.should_not be_a_parent_instrument_table
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'is a parent table when it is definitely not a child table' do
|
192
|
+
t.child_instrument_table = false
|
193
|
+
t.should be_a_parent_instrument_table
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'is not known whether it is a parent instrument table when it is not known whether it is a child instrument table' do
|
197
|
+
t.child_instrument_table = nil
|
198
|
+
t.parent_instrument_table?.should be_nil
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe '#diff' do
|
203
|
+
let(:a) { TransmissionTable.new('A') }
|
204
|
+
let(:aprime) { TransmissionTable.new('A') }
|
205
|
+
|
206
|
+
describe 'name' do
|
207
|
+
let(:b) { TransmissionTable.new('B') }
|
208
|
+
|
209
|
+
it 'reports a difference when they are different' do
|
210
|
+
a.diff(b)[:name].should be_a_value_diff('A', 'B')
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'reports nothing when they are the same' do
|
214
|
+
a.diff(aprime).should be_nil
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
describe 'variables' do
|
219
|
+
let(:v1) { Variable.new('V1') }
|
220
|
+
let(:v1prime) { Variable.new('V1') }
|
221
|
+
let(:v2) { Variable.new('V2') }
|
222
|
+
let(:v3) { Variable.new('V3') }
|
223
|
+
|
224
|
+
let(:diff) { a.diff(aprime) }
|
225
|
+
|
226
|
+
before do
|
227
|
+
a.variables << v1
|
228
|
+
aprime.variables << v1prime
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'lists variables which are in the lefthand side only' do
|
232
|
+
a.variables << v2 << v3
|
233
|
+
aprime.variables << v3
|
234
|
+
|
235
|
+
diff[:variables].left_only.should == ['V2']
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'lists variables which are in the righthand side only' do
|
239
|
+
aprime.variables << v3
|
240
|
+
|
241
|
+
diff[:variables].right_only.should == ['V3']
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'provides detailed differences for variables which are different' do
|
245
|
+
v1.pii = :possible
|
246
|
+
a.variables << v1
|
247
|
+
|
248
|
+
v1prime.pii = true
|
249
|
+
aprime.variables << v1prime
|
250
|
+
|
251
|
+
diff[:variables].entry_differences['V1'][:pii].should be_a_value_diff(:possible, true)
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'does not list variables which are the same' do
|
255
|
+
diff.should be_nil
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
182
259
|
end
|
183
260
|
end
|