Skip to content

Commit 1bde673

Browse files
committed
added tests for Document
1 parent 1c13adf commit 1bde673

File tree

3 files changed

+247
-4
lines changed

3 files changed

+247
-4
lines changed

lib/didkit/document.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ def initialize(did, json)
2525
@handles = parse_also_known_as(json['alsoKnownAs'] || [])
2626
end
2727

28+
def get_verified_handle
29+
Resolver.new.get_verified_handle(self)
30+
end
31+
32+
private
33+
2834
def parse_services(service_data)
2935
raise FormatError, "Invalid service data" unless service_data.is_a?(Array) && service_data.all? { |x| x.is_a?(Hash) }
3036

@@ -40,9 +46,5 @@ def parse_services(service_data)
4046

4147
services
4248
end
43-
44-
def get_verified_handle
45-
Resolver.new.get_verified_handle(self)
46-
end
4749
end
4850
end

spec/document_spec.rb

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
describe DIDKit::Document do
2+
subject { described_class }
3+
4+
let(:did_string) { 'did:plc:yk4dd2qkboz2yv6tpubpc6co' }
5+
let(:did) { DID.new(did_string) }
6+
let(:json_data) { load_did_json('dholms.json') }
7+
8+
describe '#initialize' do
9+
let(:base_json) { json_data }
10+
11+
context 'with valid input' do
12+
let(:json) { base_json }
13+
14+
it 'should return a Document object' do
15+
doc = subject.new(did, json)
16+
17+
doc.should be_a(DIDKit::Document)
18+
doc.did.should == did
19+
doc.json.should == json
20+
end
21+
22+
it 'should parse services from the JSON' do
23+
doc = subject.new(did, json)
24+
25+
doc.services.should be_an(Array)
26+
doc.services.length.should == 1
27+
28+
doc.services[0].should be_a(DIDKit::ServiceRecord)
29+
doc.services[0].key.should == 'atproto_pds'
30+
doc.services[0].type.should == 'AtprotoPersonalDataServer'
31+
doc.services[0].endpoint.should == 'https://pds.dholms.xyz'
32+
end
33+
34+
it 'should parse handles from the JSON' do
35+
doc = subject.new(did, json)
36+
37+
doc.handles.should == ['dholms.xyz']
38+
end
39+
end
40+
41+
context 'when id is missing' do
42+
let(:json) { base_json.dup.tap { |h| h.delete('id') } }
43+
44+
it 'should raise a format error' do
45+
expect {
46+
subject.new(did, json)
47+
}.to raise_error(DIDKit::Document::FormatError)
48+
end
49+
end
50+
51+
context 'when id is not a string' do
52+
let(:json) { base_json.merge('id' => 123) }
53+
54+
it 'should raise a format error' do
55+
expect {
56+
subject.new(did, json)
57+
}.to raise_error(DIDKit::Document::FormatError)
58+
end
59+
end
60+
61+
context 'when id does not match the DID' do
62+
let(:json) { base_json.merge('id' => 'did:plc:notmatching') }
63+
64+
it 'should raise a format error' do
65+
expect {
66+
subject.new(did, json)
67+
}.to raise_error(DIDKit::Document::FormatError)
68+
end
69+
end
70+
71+
context 'when alsoKnownAs is not an array' do
72+
let(:json) { base_json.merge('alsoKnownAs' => 'at://dholms.xyz') }
73+
74+
it 'should raise an AtHandles format error' do
75+
expect {
76+
subject.new(did, json)
77+
}.to raise_error(DIDKit::AtHandles::FormatError)
78+
end
79+
end
80+
81+
context 'when alsoKnownAs elements are not strings' do
82+
let(:json) { base_json.merge('alsoKnownAs' => [666]) }
83+
84+
it 'should raise an AtHandles format error' do
85+
expect {
86+
subject.new(did, json)
87+
}.to raise_error(DIDKit::AtHandles::FormatError)
88+
end
89+
end
90+
91+
context 'when alsoKnownAs contains multiple handles' do
92+
let(:json) {
93+
base_json.merge('alsoKnownAs' => [
94+
'at://dholms.xyz',
95+
'https://example.com',
96+
'at://other.handle'
97+
])
98+
}
99+
100+
it 'should pick those starting with at:// and remove the prefixes' do
101+
doc = subject.new(did, json)
102+
doc.handles.should == ['dholms.xyz', 'other.handle']
103+
end
104+
end
105+
106+
context 'when service is not an array' do
107+
let(:json) { base_json.merge('service' => 'not-an-array') }
108+
109+
it 'should raise a format error' do
110+
expect {
111+
subject.new(did, json)
112+
}.to raise_error(DIDKit::Document::FormatError)
113+
end
114+
end
115+
116+
context 'when service entries are not hashes' do
117+
let(:json) { base_json.merge('service' => ['invalid']) }
118+
119+
it 'should raise a format error' do
120+
expect {
121+
subject.new(did, json)
122+
}.to raise_error(DIDKit::Document::FormatError)
123+
end
124+
end
125+
126+
context 'when service entries are partially valid' do
127+
let(:services) {
128+
[
129+
{ 'id' => '#atproto_pds', 'type' => 'AtprotoPersonalDataServer', 'serviceEndpoint' => 'https://pds.dholms.xyz' },
130+
{ 'id' => 'not_a_hash', 'type' => 'AtprotoPersonalDataServer', 'serviceEndpoint' => 'https://pds.dholms.xyz' },
131+
{ 'id' => '#wrong_type', 'type' => 123, 'serviceEndpoint' => 'https://pds.dholms.xyz' },
132+
{ 'id' => '#wrong_endpoint', 'type' => 'AtprotoPersonalDataServer', 'serviceEndpoint' => 123 },
133+
{ 'id' => '#lycan', 'type' => 'LycanService', 'serviceEndpoint' => 'https://lycan.feeds.blue' }
134+
]
135+
}
136+
137+
let(:json) { base_json.merge('service' => services) }
138+
139+
it 'should only keep the valid records' do
140+
doc = subject.new(did, json)
141+
142+
doc.services.length.should == 2
143+
doc.services.map(&:key).should == ['atproto_pds', 'lycan']
144+
doc.services.map(&:type).should == ['AtprotoPersonalDataServer', 'LycanService']
145+
doc.services.map(&:endpoint).should == ['https://pds.dholms.xyz', 'https://lycan.feeds.blue']
146+
end
147+
end
148+
end
149+
150+
describe 'service helpers' do
151+
let(:service_json) {
152+
json_data.merge('service' => [
153+
{ 'id' => '#atproto_pds', 'type' => 'AtprotoPersonalDataServer', 'serviceEndpoint' => 'https://pds.dholms.xyz' },
154+
{ 'id' => '#atproto_labeler', 'type' => 'AtprotoLabeler', 'serviceEndpoint' => 'https://labels.dholms.xyz' },
155+
{ 'id' => '#lycan', 'type' => 'LycanService', 'serviceEndpoint' => 'https://lycan.feeds.blue' }
156+
])
157+
}
158+
159+
describe '#pds_endpoint' do
160+
it 'should return the endpoint of #atproto_pds' do
161+
doc = subject.new(did, service_json)
162+
doc.pds_endpoint.should == 'https://pds.dholms.xyz'
163+
end
164+
end
165+
166+
describe '#pds_host' do
167+
it 'should return the host part of #atproto_pds endpoint' do
168+
doc = subject.new(did, service_json)
169+
doc.pds_host.should == 'pds.dholms.xyz'
170+
end
171+
end
172+
173+
describe '#labeler_endpoint' do
174+
it 'should return the endpoint of #atproto_labeler' do
175+
doc = subject.new(did, service_json)
176+
doc.labeler_endpoint.should == 'https://labels.dholms.xyz'
177+
end
178+
end
179+
180+
describe '#pds_host' do
181+
it 'should return the host part of #atproto_labeler endpoint' do
182+
doc = subject.new(did, service_json)
183+
doc.labeler_host.should == 'labels.dholms.xyz'
184+
end
185+
end
186+
187+
describe '#get_service' do
188+
it 'should fetch a service by key and type' do
189+
doc = subject.new(did, service_json)
190+
191+
lycan = doc.get_service('lycan', 'LycanService')
192+
lycan.should_not be_nil
193+
lycan.endpoint.should == 'https://lycan.feeds.blue'
194+
end
195+
196+
it 'should return nil if none of the services match' do
197+
doc = subject.new(did, service_json)
198+
199+
result = doc.get_service('lycan', 'AtprotoLabeler')
200+
result.should be_nil
201+
202+
result = doc.get_service('atproto_pds', 'PDS')
203+
result.should be_nil
204+
205+
result = doc.get_service('unknown', 'Test')
206+
result.should be_nil
207+
end
208+
end
209+
210+
it 'should expose the "labeller" aliases for endpoint and host' do
211+
doc = subject.new(did, service_json)
212+
213+
doc.labeller_endpoint.should == 'https://labels.dholms.xyz'
214+
doc.labeller_host.should == 'labels.dholms.xyz'
215+
end
216+
217+
describe 'if there is no matching service' do
218+
let(:service_json) {
219+
json_data.merge('service' => [
220+
{ 'id' => '#lycan', 'type' => 'LycanService', 'serviceEndpoint' => 'https://lycan.feeds.blue' }
221+
])
222+
}
223+
224+
it 'should return nil from the relevant methods' do
225+
doc = subject.new(did, service_json)
226+
227+
doc.pds_endpoint.should be_nil
228+
doc.pds_host.should be_nil
229+
doc.labeller_endpoint.should be_nil
230+
doc.labeller_host.should be_nil
231+
doc.labeler_endpoint.should be_nil
232+
doc.labeler_host.should be_nil
233+
end
234+
end
235+
end
236+
end

spec/spec_helper.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

33
require 'didkit'
4+
require 'json'
45
require 'webmock/rspec'
56

67
RSpec.configure do |config|
@@ -21,3 +22,7 @@
2122
def load_did_file(name)
2223
File.read(File.join(__dir__, 'dids', name))
2324
end
25+
26+
def load_did_json(name)
27+
JSON.parse(load_did_file(name))
28+
end

0 commit comments

Comments
 (0)