gexf 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ BOOLEAN_GETTERS = %w(directed? undirected? mutual?)
4
+
5
+ describe GEXF::Edge do
6
+
7
+ let(:id) { 1 }
8
+ let(:type) { nil }
9
+ let(:source_id) { 2 }
10
+ let(:target_id) { 232 }
11
+ let(:graph) { double('graph', :edges => []) }
12
+ let(:weight) { nil }
13
+ let(:label) { 'my-edge' }
14
+ let(:options) { { :graph => graph, :type => type, :weight => weight, :label => label } }
15
+ let(:arguments){ [id, source_id, target_id, options] }
16
+
17
+ subject { GEXF::Edge.new(*arguments) }
18
+
19
+ describe "#new" do
20
+ its(:id) { should == id.to_s }
21
+ its(:source_id) { should == source_id.to_s }
22
+ its(:target_id) { should == target_id.to_s }
23
+ its(:weight) { should == 1.0 }
24
+ its(:label) { should == label }
25
+ its(:type) { should == GEXF::Edge::UNDIRECTED }
26
+
27
+ [:id, :source_id, :target_id, :graph].each do |param|
28
+ context "when :#{param} is missing" do
29
+ let(param) { nil }
30
+
31
+ it "raises an ArgumentError" do
32
+ expect { subject }.to raise_error(ArgumentError)
33
+ end
34
+ end
35
+ end
36
+
37
+ context "non-positive :weight" do
38
+ let(:weight) { -10 }
39
+
40
+ it "raises an ArgumentError" do
41
+ expect { subject }.to raise_error(ArgumentError)
42
+ end
43
+ end
44
+
45
+ context "invalid type" do
46
+ let(:type) { :FOOBAR }
47
+
48
+ it "raises an ArgumentError" do
49
+ expect { subject }.to raise_error(ArgumentError)
50
+ end
51
+ end
52
+ end
53
+
54
+ BOOLEAN_GETTERS.each do |method|
55
+ edge_type = GEXF::Edge.const_get(method[0..-2].upcase.to_sym)
56
+ other_getters = BOOLEAN_GETTERS - [method]
57
+
58
+ describe(method) do
59
+ context "when type is :#{edge_type}" do
60
+ let(:type) { edge_type }
61
+
62
+ its(method) { should be_true }
63
+
64
+ other_getters.each do |other_type|
65
+ its(other_type) { should be_false }
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+
3
+ describe GEXF::EdgeSet do
4
+
5
+ def make_edge(attr={})
6
+ mock('edge', :source_id => attr[:source_id],
7
+ :target_id => attr[:target_id],
8
+ :directed? => attr[:type] == GEXF::Edge::DIRECTED,
9
+ :undirected? => attr[:type] == GEXF::Edge::UNDIRECTED)
10
+ end
11
+
12
+ let(:source_id) { '1' }
13
+ let(:target_id) { '11' }
14
+ let(:type) { GEXF::Edge::DIRECTED }
15
+ let(:attrs) { { :type => type,
16
+ :source_id => source_id,
17
+ :target_id => target_id }}
18
+
19
+ let(:arguments) { [] }
20
+ let(:edge) { make_edge(attrs) }
21
+
22
+ let(:edge2) { make_edge(:type => GEXF::Edge::UNDIRECTED,
23
+ :source_id => '2',
24
+ :target_id => '22') }
25
+
26
+ let(:edge3) { make_edge(:type => GEXF::Edge::DIRECTED,
27
+ :source_id => '3',
28
+ :target_id => '33') }
29
+
30
+ let(:edge4) { make_edge(:type => GEXF::Edge::DIRECTED,
31
+ :source_id => '3',
32
+ :target_id => '22') }
33
+
34
+
35
+ let(:edgeset) { GEXF::EdgeSet.new(*arguments) }
36
+
37
+ describe "#<<" do
38
+ subject { edgeset << edge }
39
+
40
+ context "when edge is directed" do
41
+ it "adds the edge to the @data hash, using the :source_id as key" do
42
+ subject.to_hash.should have_key(edge.source_id)
43
+ subject.to_hash.should_not have_key(edge.target_id)
44
+ end
45
+ end
46
+
47
+ context "when edge is undirected" do
48
+ let(:type) { GEXF::Edge::UNDIRECTED }
49
+
50
+ it "adds the edge to the data hash, using both :source_id, and the :target_id as keys" do
51
+ subject.to_hash.should have_key(edge.source_id)
52
+ subject.to_hash.should have_key(edge.target_id)
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "#count" do
58
+ let(:other_edge) { make_edge(:type => other_edge_type,
59
+ :source_id => '3',
60
+ :target_id => '33') }
61
+
62
+ subject { edgeset << edge << other_edge }
63
+
64
+ context "when adding two directed edges" do
65
+ let(:other_edge_type) { GEXF::Edge::DIRECTED }
66
+
67
+ it "creates 2 keys in the hash, returns 2" do
68
+ subject.should have(2).items
69
+ subject.to_hash.keys.should have(2).items
70
+ end
71
+ end
72
+
73
+ context "when adding a directed and an undirected edge" do
74
+ let(:other_edge_type) { GEXF::Edge::UNDIRECTED }
75
+
76
+ it "creates 3 keys in the hash, returns 2" do
77
+ subject.should have(2).items
78
+ subject.to_hash.keys.should have(3).items
79
+ end
80
+ end
81
+ end
82
+
83
+ describe "#map" do
84
+ subject { edgeset << edge << edge2 << edge3 << edge4 }
85
+
86
+ it "returns a list of unique edges" do
87
+ subject.map(&:source_id).should == ['1', '2', '3', '3']
88
+ subject.map(&:target_id).should == ['11', '22', '33', '22']
89
+ end
90
+
91
+ end
92
+
93
+ describe "#select" do
94
+ subject { edgeset << edge << edge2 << edge3 }
95
+
96
+ it "selects two directed edges" do
97
+ subject.select(&:directed?).should include(edge, edge3)
98
+ end
99
+ it "selects an undirected edge" do
100
+ subject.select(&:undirected?).should include(edge2)
101
+ end
102
+ end
103
+
104
+ end
105
+
@@ -0,0 +1,172 @@
1
+ require 'spec_helper'
2
+
3
+ describe GEXF::Graph do
4
+ let(:edgetype) { nil }
5
+ let(:idtype) { nil }
6
+ let(:mode) { nil }
7
+ let(:opts) {{ :defaultedgetype => edgetype,
8
+ :idtype => idtype,
9
+ :mode => mode }}
10
+
11
+ let(:graph) { GEXF::Graph.new(opts) }
12
+
13
+
14
+ describe "default getters" do
15
+ subject { graph }
16
+
17
+ context "when params are valid" do
18
+ its(:defaultedgetype) { should == GEXF::Edge::UNDIRECTED }
19
+ its(:idtype) { should == GEXF::Graph::STRING }
20
+ its(:mode) { should == GEXF::Graph::STATIC }
21
+ its(:nodes) { should be_empty }
22
+ its(:edges) { should be_empty }
23
+ end
24
+
25
+ context "when params are not valid" do
26
+ [:defaultedgetype, :idtype, :mode].each do |param|
27
+
28
+ let(param) { :FOO }
29
+
30
+ describe "when #{param} is invalid" do
31
+ it "raises an argument error" do
32
+ expect { subject }.to raise_error(ArgumentError)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ describe "#define_node_attribute" do
40
+ let(:attr_type) { GEXF::Attribute::STRING }
41
+ let(:attr_id) { nil }
42
+ let(:default) { 'home sweet home' }
43
+ let(:title) { 'page-title' }
44
+ let(:attr_opts) {{ :default => default,
45
+ :attr_id => attr_id }}
46
+
47
+
48
+ subject { graph.define_node_attribute(title, attr_opts) }
49
+
50
+ it "delegates to @nodes" do
51
+
52
+ new_attribute = double('attribute')
53
+
54
+ graph.nodes.should_receive(:define_attribute).
55
+ with('1', title, attr_opts).
56
+ and_return(new_attribute)
57
+
58
+ subject.should == new_attribute
59
+ end
60
+ end
61
+
62
+ describe "#define_edge_attribute" do
63
+ let(:attr_type) { GEXF::Attribute::STRING }
64
+ let(:attr_id) { nil }
65
+ let(:default) { 'home sweet home' }
66
+ let(:title) { 'page-title' }
67
+ let(:attr_opts) {{ :default => default,
68
+ :attr_id => attr_id }}
69
+
70
+
71
+ subject { graph.define_edge_attribute(title, attr_opts) }
72
+
73
+ it "delegates to @nodes" do
74
+
75
+ new_attribute = double('attribute')
76
+
77
+ graph.edges.should_receive(:define_attribute).
78
+ with('1', title, attr_opts).
79
+ and_return(new_attribute)
80
+
81
+ subject.should == new_attribute
82
+ end
83
+ end
84
+
85
+ describe "#create_node" do
86
+ let(:node_id) { 'node_21' }
87
+ let(:node_opts) {{ :label => 'my node' }}
88
+ let(:create_opts) { node_opts }
89
+
90
+ before(:each) do
91
+ @node = mock('node')
92
+ nodeset = mock('nodeset')
93
+
94
+ GEXF::NodeSet.stub(:new).and_return(nodeset)
95
+ nodeset.should_receive(:<<).at_least(:once).with(@node)
96
+ end
97
+
98
+ context "when :id is provided" do
99
+ let(:create_opts) { node_opts.merge(:id => node_id) }
100
+
101
+ it "uses the id provided to create a node" do
102
+ GEXF::Node.should_receive(:new).
103
+ with(node_id, graph, node_opts).
104
+ and_return(@node)
105
+
106
+ graph.create_node(create_opts) == @node
107
+ end
108
+ end
109
+
110
+ context "when :id is not provided" do
111
+ it "auto-assigns the id using the internal counter" do
112
+ 3.times do |n|
113
+ GEXF::Node.should_receive(:new).
114
+ once.ordered.
115
+ with((n+1).to_s, graph, node_opts).
116
+ and_return(@node)
117
+ end
118
+
119
+ 3.times { graph.create_node(create_opts) }
120
+ end
121
+ end
122
+ end
123
+
124
+ describe "#create_edge" do
125
+ let(:edge_label) { 'bar' }
126
+ let(:source_id) { '2' }
127
+ let(:target_id) { '32' }
128
+ let(:source) { mock('source', :id => source_id) }
129
+ let(:target) { mock('target', :id => target_id) }
130
+ let(:edge_opts) {{:label => edge_label }}
131
+
132
+ subject { graph.create_edge(source, target, edge_opts) }
133
+
134
+ before(:each) do
135
+ @edge = mock('edge')
136
+ edgeset = mock('edgeset')
137
+
138
+ GEXF::EdgeSet.stub(:new).and_return(edgeset)
139
+ edgeset.should_receive(:<<).at_least(:once).with(@edge)
140
+ end
141
+
142
+ context "when no :id or :type param is provided" do
143
+ it "auto-assigns the edge :id using the internal counter, and the :type using :edgetype" do
144
+
145
+ GEXF::Edge.should_receive(:new).
146
+ with('1', source.id, target.id, edge_opts.merge(:graph => graph,
147
+ :type => graph.defaultedgetype)).
148
+ and_return(@edge)
149
+
150
+ subject.should == @edge
151
+ end
152
+ end
153
+
154
+ context "when an :id and a :type are provided" do
155
+
156
+ let(:edge_id) { 'myedge-33' }
157
+ let(:edge_opts) {{ :label => edge_label,
158
+ :id => edge_id,
159
+ :type => GEXF::Edge::DIRECTED }}
160
+
161
+ it "passes the params to the Edge constructor" do
162
+ expected_opts = edge_opts.reject {|k,v| k == :id }.merge(:graph => graph)
163
+
164
+ GEXF::Edge.should_receive(:new).
165
+ with(edge_id, source.id, target.id, expected_opts).
166
+ and_return(@edge)
167
+
168
+ subject.should == @edge
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+
3
+ describe GEXF::Node do
4
+
5
+ let(:indegree) { GEXF::Attribute.new('1', 'indegree', type: GEXF::Attribute::INTEGER) }
6
+ let(:outdegree) { GEXF::Attribute.new('2', 'outdegree', type: GEXF::Attribute::INTEGER) }
7
+
8
+ let(:attribute_definitions) {{ '1' => indegree,
9
+ '2' => outdegree }}
10
+
11
+ let(:id) { 22 }
12
+ let(:idtype) { GEXF::Graph::STRING }
13
+ let(:collection) { mock('nodeset', :attribute_definitions => attribute_definitions) }
14
+ let(:edges) { mock('edgeset') }
15
+ let(:graph) { double('graph', :nodes => collection, :idtype => idtype, :edges => edges) }
16
+ let(:label) { 'foo' }
17
+ let(:attributes) {{ }}
18
+ let(:options) {{ :label => label, :attributes => attributes }}
19
+ let(:arguments) { [id, graph, options] }
20
+ let(:node) { GEXF::Node.new(*arguments) }
21
+
22
+ subject { node }
23
+
24
+ it "includes the GEXF::Attribute::Assignable module" do
25
+ subject.class.include?(GEXF::Attribute::Assignable)
26
+ end
27
+
28
+ context "when graph :idtype is string" do
29
+ its(:id) { should == id.to_s }
30
+ end
31
+
32
+ context "when graph :idtype is integer" do
33
+ let(:idtype) { GEXF::Graph::INTEGER }
34
+ its(:id) { should == id.to_i }
35
+ end
36
+
37
+ describe "#label" do
38
+ context "option provided" do
39
+ its(:label) { should == label }
40
+ end
41
+ context "option omitted" do
42
+ let(:options) {{}}
43
+ its(:label) { should == id.to_s }
44
+ end
45
+ end
46
+
47
+ describe "attributes" do
48
+ context "when no attributes are defined" do
49
+ let(:attribute_definitions) {{}}
50
+ its(:attributes) { should be_empty }
51
+ end
52
+ context "when no attributes are supplied" do
53
+ its(:attributes) { should == { 'indegree' => nil, 'outdegree' => nil }}
54
+ end
55
+ context "when attributes are supplied" do
56
+ let(:attributes) {{ :outdegree => '24' }}
57
+ its(:attributes) { should == { 'indegree' => nil, 'outdegree' => 24 }}
58
+ end
59
+ end
60
+
61
+ describe "#connect_to" do
62
+
63
+ let(:edge_opts) {{ :type => GEXF::Edge::DIRECTED }}
64
+ let(:other_node) { mock('other_node') }
65
+ let(:new_edge) { mock('new-edge') }
66
+
67
+ subject { node.connect_to(other_node, edge_opts) }
68
+
69
+ it "adds the target to the nodes collection, creates and returns a new edge" do
70
+
71
+ collection.should_receive(:<<).with(other_node)
72
+
73
+ graph.should_receive(:create_edge).
74
+ with(node, other_node, edge_opts).
75
+ and_return(new_edge)
76
+
77
+ subject.should == new_edge
78
+ end
79
+ end
80
+
81
+ describe "#create_and_connect_to" do
82
+ let(:edge_opts) {{ :type => GEXF::Edge::DIRECTED }}
83
+ let(:node_attrs) {{ :label => 'other node'}}
84
+ let(:new_node) { mock('new_node') }
85
+
86
+ subject { node.create_and_connect_to(node_attrs, edge_opts) }
87
+
88
+ it "creates the node, adds it to nodes collection, and returns it" do
89
+ graph.should_receive(:create_node).with(node_attrs).and_return(new_node)
90
+ collection.should_receive(:<<).with(new_node)
91
+ graph.should_receive(:create_edge).with(node, new_node, edge_opts)
92
+
93
+ subject.should == new_node
94
+ end
95
+ end
96
+
97
+ describe "#connections" do
98
+ subject { node.connections }
99
+
100
+ it "delegates to graph.edges[node.id]" do
101
+ edges.should_receive(:[]).with(node.id)
102
+ subject
103
+ end
104
+ end
105
+ end