familysearch-gedcomx 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+ require 'json'
3
+
4
+ describe FamilySearch::Gedcomx::Graph do
5
+ subject(:graph) { FamilySearch::Gedcomx::Graph.new }
6
+ describe "Initializing" do
7
+ it "should have an array of persons" do
8
+ graph.persons.should be_a_kind_of(Array)
9
+ end
10
+
11
+ end
12
+
13
+ describe "#<< adding Person objects" do
14
+ before(:each) do
15
+ @familysearch = FamilySearch::Gedcomx::FamilySearch.new(JSON.parse(File.read('spec/familysearch/gedcomx/fixtures/person-with-relationships.json')))
16
+ end
17
+
18
+ it "should accept a Person object" do
19
+ graph << @familysearch
20
+ end
21
+
22
+ it "should convert the Person object into a GraphPerson" do
23
+ graph << @familysearch
24
+ graph.persons[0].class.should == FamilySearch::Gedcomx::GraphPerson
25
+ end
26
+
27
+ it "should assign the Graph object to the GraphPerson instance" do
28
+ graph << @familysearch
29
+ graph.persons[0].graph.should == graph
30
+ end
31
+
32
+ it "should be able to retrieve by person ID" do
33
+ graph << @familysearch
34
+ graph.person('L7PD-KY3').id.should == 'L7PD-KY3'
35
+ end
36
+
37
+ it "should set the root as the first thing added" do
38
+ graph << @familysearch
39
+ graph.root.id.should == 'L7PD-KY3'
40
+ end
41
+
42
+ it "should set a property of childAndParentsRelationships" do
43
+ graph << @familysearch
44
+ graph.childAndParentsRelationships.should == @familysearch.childAndParentsRelationships
45
+ end
46
+
47
+ context "adding multiple people to graph" do
48
+ before(:each) do
49
+ @fs_mother = FamilySearch::Gedcomx::FamilySearch.new(JSON.parse(File.read('spec/familysearch/gedcomx/fixtures/person-with-relationships-mother.json')))
50
+ @fs_father = FamilySearch::Gedcomx::FamilySearch.new(JSON.parse(File.read('spec/familysearch/gedcomx/fixtures/person-with-relationships-father.json')))
51
+ graph << @familysearch
52
+ end
53
+
54
+ it "should add the mother and father to the graph and still have the child" do
55
+ graph << @fs_mother
56
+ graph << @fs_father
57
+ graph.persons.size.should == 3
58
+ graph.person('L78M-TD6').id.should == @fs_mother.persons[0].id
59
+ graph.person('L78M-RLN').id.should == @fs_father.persons[0].id
60
+ end
61
+
62
+ it "should keep the root as the first person added" do
63
+ graph << @fs_mother
64
+ graph << @fs_father
65
+ graph.root.id.should == @familysearch.persons[0].id
66
+ end
67
+
68
+ it "should add the mother's relationships to the childAndParentsRelationships" do
69
+ cpr_ids = graph.childAndParentsRelationships.collect{|cpr|cpr.id}
70
+ graph << @fs_mother
71
+ graph << @fs_father
72
+ new_cpr_ids = graph.childAndParentsRelationships.collect{|cpr|cpr.id}
73
+ (new_cpr_ids & cpr_ids).should == cpr_ids
74
+ end
75
+
76
+ it "should not do anything if you add the same person twice" do
77
+ graph << @fs_mother
78
+ b4_size = graph.persons.size
79
+ b4_cpr_ids = graph.childAndParentsRelationships.collect{|cpr|cpr.id}
80
+ graph << @fs_mother
81
+ graph.persons.size.should == b4_size
82
+ cpr_ids = graph.childAndParentsRelationships.collect{|cpr|cpr.id}
83
+ cpr_ids.should == b4_cpr_ids
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,178 @@
1
+ require 'spec_helper'
2
+ require 'json'
3
+
4
+ describe FamilySearch::Gedcomx::Person do
5
+ subject { FamilySearch::Gedcomx::FamilySearch.new(JSON.parse(File.read('spec/familysearch/gedcomx/fixtures/person.json'))).persons[0] }
6
+
7
+ context "convenience methods" do
8
+ describe "#name" do
9
+ it 'should provide the first names array ' do
10
+ subject.name.class.should == FamilySearch::Gedcomx::Name
11
+ end
12
+
13
+ it "should return nil if names array is empty or nil" do
14
+ subject.names = []
15
+ subject.name.should == nil
16
+ subject.names = nil
17
+ subject.name.should == nil
18
+ end
19
+
20
+ it "should have a fullText that defaults to the first nameForm's fullText" do
21
+ subject.name.fullText.should == "Marshall P Felch"
22
+ end
23
+
24
+ it "should return \"\" if anything in the path is nil" do
25
+ subject.names[0].nameForms = nil
26
+ subject.name.fullText.should == ""
27
+ subject.names[0].nameForms = []
28
+ subject.name.fullText.should == ""
29
+ end
30
+ end
31
+
32
+ describe "#full_name" do
33
+ it "should return the first name's first nameForm's fullText" do
34
+ subject.full_name.should == "Marshall P Felch"
35
+ end
36
+
37
+ it "should return '' if there are no names" do
38
+ subject.names = []
39
+ subject.full_name.should == ''
40
+ subject.names = nil
41
+ subject.full_name.should == ''
42
+ end
43
+ end
44
+
45
+ describe "#surname" do
46
+ it "should return the surname of the first name's first nameForm" do
47
+ subject.surname.should == "Felch"
48
+ end
49
+
50
+ it "should return '' if there is a nil anywhere in the process" do
51
+ subject.names[0].nameForms[0].parts = []
52
+ subject.surname.should == ''
53
+ subject.names[0].nameForms[0].parts = nil
54
+ subject.surname.should == ''
55
+ subject.names[0].nameForms = []
56
+ subject.surname.should == ''
57
+ subject.names[0].nameForms = nil
58
+ subject.surname.should == ''
59
+ subject.names= []
60
+ subject.surname.should == ''
61
+ subject.names= nil
62
+ subject.surname.should == ''
63
+ end
64
+ end
65
+
66
+ describe "#given_name" do
67
+ it "should return the surname of the first name's first nameForm" do
68
+ subject.given_name.should == "Marshall P"
69
+ end
70
+
71
+ it "should return '' if there is a nil anywhere in the process" do
72
+ subject.names[0].nameForms[0].parts = []
73
+ subject.given_name.should == ''
74
+ subject.names[0].nameForms[0].parts = nil
75
+ subject.given_name.should == ''
76
+ subject.names[0].nameForms = []
77
+ subject.given_name.should == ''
78
+ subject.names[0].nameForms = nil
79
+ subject.given_name.should == ''
80
+ subject.names= []
81
+ subject.given_name.should == ''
82
+ subject.names= nil
83
+ subject.given_name.should == ''
84
+ end
85
+ end
86
+
87
+
88
+ describe "#id" do
89
+ it "should return the person's id" do
90
+ subject.id.should == "L7PD-KY3"
91
+ end
92
+ end
93
+
94
+ describe "#birth" do
95
+ it "should return the person's first birth event" do
96
+ subject.birth.class.should == FamilySearch::Gedcomx::Fact
97
+ end
98
+
99
+ it "should return nil if there is no birth event" do
100
+ subject.birth.type = "http://gedcomx.org/SomethingElse"
101
+ subject.birth.should == nil
102
+ end
103
+
104
+ it "should return nil if there are no facts" do
105
+ subject.facts = []
106
+ subject.birth.should == nil
107
+ subject.facts = nil
108
+ subject.birth.should == nil
109
+ end
110
+ end
111
+
112
+ describe "#death" do
113
+ it "should return the person's first death event" do
114
+ subject.death.class.should == FamilySearch::Gedcomx::Fact
115
+ end
116
+
117
+ it "should have the type of http://gedcomx.org/Death" do
118
+ subject.death.type.should == "http://gedcomx.org/Death"
119
+ end
120
+
121
+ it "should return nil if there is no birth event" do
122
+ subject.death.type = "http://gedcomx.org/SomethingElse"
123
+ subject.death.should == nil
124
+ end
125
+
126
+ it "should return nil if there are no facts" do
127
+ subject.facts = []
128
+ subject.death.should == nil
129
+ subject.facts = nil
130
+ subject.death.should == nil
131
+ end
132
+ end
133
+
134
+ describe "#christening" do
135
+ it "should return the person's first death event" do
136
+ subject.christening.class.should == FamilySearch::Gedcomx::Fact
137
+ end
138
+
139
+ it "should have the type of http://gedcomx.org/Christening" do
140
+ subject.christening.type.should == "http://gedcomx.org/Christening"
141
+ end
142
+
143
+ it "should return nil if there is no birth event" do
144
+ subject.christening.type = "http://gedcomx.org/SomethingElse"
145
+ subject.christening.should == nil
146
+ end
147
+
148
+ it "should return nil if there are no facts" do
149
+ subject.facts = []
150
+ subject.christening.should == nil
151
+ subject.facts = nil
152
+ subject.christening.should == nil
153
+ end
154
+ end
155
+
156
+ describe "#burial" do
157
+ it "should return the person's first death event" do
158
+ subject.burial.class.should == FamilySearch::Gedcomx::Fact
159
+ end
160
+
161
+ it "should have the type of http://gedcomx.org/Burial" do
162
+ subject.burial.type.should == "http://gedcomx.org/Burial"
163
+ end
164
+
165
+ it "should return nil if there is no birth event" do
166
+ subject.burial.type = "http://gedcomx.org/SomethingElse"
167
+ subject.burial.should == nil
168
+ end
169
+
170
+ it "should return nil if there are no facts" do
171
+ subject.facts = []
172
+ subject.burial.should == nil
173
+ subject.facts = nil
174
+ subject.burial.should == nil
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,321 @@
1
+ # This spec was copied and modified from the Hashie gem
2
+ #
3
+ # Copyright (c) 2009 Intridea, Inc.
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.
23
+
24
+ require 'spec_helper'
25
+ require 'hashie/extensions/coercion'
26
+
27
+ Hashie::Hash.class_eval do
28
+ def self.inherited(klass)
29
+ klass.instance_variable_set('@inheritance_test', true)
30
+ end
31
+ end
32
+
33
+ class DashTest < FamilySearch::Gedcomx::SuperDash
34
+ property :first_name, :required => true
35
+ property :email
36
+ property :count, :default => 0
37
+ end
38
+
39
+ class DashNoRequiredTest < FamilySearch::Gedcomx::SuperDash
40
+ property :first_name
41
+ property :email
42
+ property :count, :default => 0
43
+ end
44
+
45
+ class Subclassed < DashTest
46
+ property :last_name, :required => true
47
+ end
48
+
49
+ class DashDefaultTest < FamilySearch::Gedcomx::SuperDash
50
+ property :aliases, :default => ["Snake"]
51
+ end
52
+
53
+ class DashCoercionTest < FamilySearch::Gedcomx::SuperDash
54
+ include FamilySearch::Gedcomx::SuperCoercion
55
+ property :dash_test
56
+ coerce_key :dash_test, DashTest
57
+ end
58
+
59
+ class DeferredTest < FamilySearch::Gedcomx::SuperDash
60
+ property :created_at, :default => Proc.new { Time.now }
61
+ end
62
+
63
+ class DashesInArray < FamilySearch::Gedcomx::SuperDash
64
+ include FamilySearch::Gedcomx::SuperCoercion
65
+ property :dash_tests
66
+ property :dash_hash
67
+ coerce_key :dash_tests, [DashTest]
68
+ coerce_key :dash_hash, {'key' => DashTest}
69
+ end
70
+
71
+ describe DashTest do
72
+
73
+ subject { DashTest.new(:first_name => 'Bob', :email => 'bob@example.com') }
74
+
75
+ it('subclasses Hashie::Hash') { should respond_to(:to_mash) }
76
+
77
+ its(:to_s) { should == '#<DashTest count=0 email="bob@example.com" first_name="Bob">' }
78
+
79
+ it 'lists all set properties in inspect' do
80
+ subject.first_name = 'Bob'
81
+ subject.email = 'bob@example.com'
82
+ subject.inspect.should == '#<DashTest count=0 email="bob@example.com" first_name="Bob">'
83
+ end
84
+
85
+ its(:count) { should be_zero }
86
+
87
+ it { should respond_to(:first_name) }
88
+ it { should respond_to(:first_name=) }
89
+ it { should_not respond_to(:nonexistent) }
90
+
91
+ it 'does not error out for a non-existent property' do
92
+ lambda { subject['nonexistent'] }.should_not raise_error(NoMethodError)
93
+ end
94
+
95
+ it 'errors out when attempting to set a required property to nil' do
96
+ lambda { subject.first_name = nil }.should raise_error(ArgumentError)
97
+ end
98
+
99
+ context 'writing to properties' do
100
+
101
+ it 'fails writing a required property to nil' do
102
+ lambda { subject.first_name = nil }.should raise_error(ArgumentError)
103
+ end
104
+
105
+ it 'fails writing a required property to nil using []=' do
106
+ lambda { subject['first_name'] = nil }.should raise_error(ArgumentError)
107
+ end
108
+
109
+ it 'succeeds writing to a non-existent property using []=' do
110
+ lambda { subject['nonexistent'] = 123 }.should_not raise_error(NoMethodError)
111
+ end
112
+
113
+ it 'works for an existing property using []=' do
114
+ subject['first_name'] = 'Bob'
115
+ subject['first_name'].should == 'Bob'
116
+ subject[:first_name].should == 'Bob'
117
+ end
118
+
119
+ it 'works for an existing property using a method call' do
120
+ subject.first_name = 'Franklin'
121
+ subject.first_name.should == 'Franklin'
122
+ end
123
+ end
124
+
125
+ context 'reading from properties' do
126
+ it 'succeeds reading from a non-existent property using []' do
127
+ lambda { subject['nonexistent'] }.should_not raise_error(NoMethodError)
128
+ end
129
+
130
+ it "should be able to retrieve properties through blocks" do
131
+ subject["first_name"] = "Aiden"
132
+ value = nil
133
+ subject.[]("first_name") { |v| value = v }
134
+ value.should == "Aiden"
135
+ end
136
+
137
+ it "should be able to retrieve properties through blocks with method calls" do
138
+ subject["first_name"] = "Frodo"
139
+ value = nil
140
+ subject.first_name { |v| value = v }
141
+ value.should == "Frodo"
142
+ end
143
+ end
144
+
145
+ context 'reading from deferred properties' do
146
+ it 'should evaluate proc after initial read' do
147
+ DeferredTest.new['created_at'].should be_instance_of(Time)
148
+ end
149
+
150
+ it "should not evalute proc after subsequent reads" do
151
+ deferred = DeferredTest.new
152
+ deferred['created_at'].object_id.should == deferred['created_at'].object_id
153
+ end
154
+ end
155
+
156
+ describe '.new' do
157
+ it 'fails with non-existent properties' do
158
+ lambda { described_class.new(:bork => '') }.should_not raise_error(NoMethodError)
159
+ end
160
+
161
+ it 'should set properties that it is able to' do
162
+ obj = described_class.new :first_name => 'Michael'
163
+ obj.first_name.should == 'Michael'
164
+ end
165
+
166
+ it 'accepts nil' do
167
+ lambda { DashNoRequiredTest.new(nil) }.should_not raise_error
168
+ end
169
+
170
+ it 'accepts block to define a global default' do
171
+ obj = described_class.new { |hash, key| key.to_s.upcase }
172
+ obj.first_name.should == 'FIRST_NAME'
173
+ obj.count.should be_zero
174
+ end
175
+
176
+ it "fails when required values are missing" do
177
+ expect { DashTest.new }.to raise_error(ArgumentError)
178
+ end
179
+
180
+ it "does not overwrite default values" do
181
+ obj1 = DashDefaultTest.new
182
+ obj1.aliases << "El Rey"
183
+ obj2 = DashDefaultTest.new
184
+ obj2.aliases.should_not include "El Rey"
185
+ end
186
+ end
187
+
188
+ describe 'properties' do
189
+ it 'lists defined properties' do
190
+ described_class.properties.should == Set.new([:first_name, :email, :count])
191
+ end
192
+
193
+ it 'checks if a property exists' do
194
+ described_class.property?('first_name').should be_true
195
+ described_class.property?(:first_name).should be_true
196
+ end
197
+
198
+ it 'checks if a property is required' do
199
+ described_class.required?('first_name').should be_true
200
+ described_class.required?(:first_name).should be_true
201
+ end
202
+
203
+ it 'doesnt include property from subclass' do
204
+ described_class.property?(:last_name).should be_false
205
+ end
206
+
207
+ it 'lists declared defaults' do
208
+ described_class.defaults.should == { :count => 0 }
209
+ end
210
+ end
211
+
212
+ describe '#replace' do
213
+ before { subject.replace(:first_name => "Cain") }
214
+
215
+ it 'return self' do
216
+ subject.replace(:email => "bar").to_hash.
217
+ should == {"email" => "bar", "count" => 0}
218
+ end
219
+
220
+ it 'sets all specified keys to their corresponding values' do
221
+ subject.first_name.should == "Cain"
222
+ end
223
+
224
+ it 'leaves only specified keys and keys with default values' do
225
+ subject.keys.sort.should == ['count', 'first_name']
226
+ subject.email.should be_nil
227
+ subject.count.should == 0
228
+ end
229
+
230
+ context 'when replacing keys with default values' do
231
+ before { subject.replace(:count => 3) }
232
+
233
+ it 'sets all specified keys to their corresponding values' do
234
+ subject.count.should == 3
235
+ end
236
+ end
237
+ end
238
+ end
239
+
240
+ describe FamilySearch::Gedcomx::SuperDash, 'inheritance' do
241
+ before do
242
+ @top = Class.new(FamilySearch::Gedcomx::SuperDash)
243
+ @middle = Class.new(@top)
244
+ @bottom = Class.new(@middle)
245
+ end
246
+
247
+ it 'reports empty properties when nothing defined' do
248
+ @top.properties.should be_empty
249
+ @top.defaults.should be_empty
250
+ end
251
+
252
+ it 'inherits properties downwards' do
253
+ @top.property :echo
254
+ @middle.properties.should include(:echo)
255
+ @bottom.properties.should include(:echo)
256
+ end
257
+
258
+ it 'doesnt inherit properties upwards' do
259
+ @middle.property :echo
260
+ @top.properties.should_not include(:echo)
261
+ @bottom.properties.should include(:echo)
262
+ end
263
+
264
+ it 'allows overriding a default on an existing property' do
265
+ @top.property :echo
266
+ @middle.property :echo, :default => 123
267
+ @bottom.properties.to_a.should == [:echo]
268
+ @bottom.new.echo.should == 123
269
+ end
270
+
271
+ it 'allows clearing an existing default' do
272
+ @top.property :echo
273
+ @middle.property :echo, :default => 123
274
+ @bottom.property :echo
275
+ @bottom.properties.to_a.should == [:echo]
276
+ @bottom.new.echo.should be_nil
277
+ end
278
+
279
+ it 'should allow nil defaults' do
280
+ @bottom.property :echo, :default => nil
281
+ @bottom.new.should have_key('echo')
282
+ end
283
+
284
+ end
285
+
286
+ describe Subclassed do
287
+
288
+ subject { Subclassed.new(:first_name => 'Bob', :last_name => 'McNob', :email => 'bob@example.com') }
289
+
290
+ its(:count) { should be_zero }
291
+
292
+ it { should respond_to(:first_name) }
293
+ it { should respond_to(:first_name=) }
294
+ it { should respond_to(:last_name) }
295
+ it { should respond_to(:last_name=) }
296
+
297
+ it 'has one additional property' do
298
+ described_class.property?(:last_name).should be_true
299
+ end
300
+
301
+ it "didn't override superclass inheritance logic" do
302
+ described_class.instance_variable_get('@inheritance_test').should be_true
303
+ end
304
+
305
+ end
306
+
307
+
308
+ describe DashCoercionTest do
309
+ subject { DashCoercionTest.new(:dash_test => {:first_name => 'Bob', :email => 'bob@example.com'}) }
310
+ it "should coerce the properties into its right value" do
311
+ subject.dash_test.should be_instance_of(DashTest)
312
+ end
313
+ end
314
+
315
+ describe DashesInArray do
316
+ subject { DashesInArray.new(:dash_tests => [{:first_name => 'Bob', :email => 'bob@example.com'},{:first_name => 'Bobby', :email => 'bobby@example.com'}], :dash_hash => {'first' => {:first_name => 'Bob', :email => 'bob@example.com'}, 'second' => {:first_name => 'Bobby', :email => 'bobby@example.com'}}) }
317
+ it "should coerce the properties into its right value" do
318
+ subject.dash_tests[0].should be_instance_of(DashTest)
319
+ subject.dash_hash['first'].should be_instance_of(DashTest)
320
+ end
321
+ end