roadforest 0.5 → 0.7

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/examples/file-management.rb +70 -58
  3. data/lib/roadforest/application.rb +9 -17
  4. data/lib/roadforest/application/dispatcher.rb +76 -9
  5. data/lib/roadforest/application/parameters.rb +9 -1
  6. data/lib/roadforest/application/path-provider.rb +30 -3
  7. data/lib/roadforest/application/route-adapter.rb +96 -14
  8. data/lib/roadforest/application/services-host.rb +21 -3
  9. data/lib/roadforest/augment/affordance.rb +82 -11
  10. data/lib/roadforest/augment/augmentation.rb +24 -6
  11. data/lib/roadforest/augment/augmenter.rb +12 -3
  12. data/lib/roadforest/authorization.rb +7 -229
  13. data/lib/roadforest/authorization/auth-entity.rb +26 -0
  14. data/lib/roadforest/authorization/authentication-chain.rb +79 -0
  15. data/lib/roadforest/authorization/default-authentication-store.rb +33 -0
  16. data/lib/roadforest/authorization/grant-builder.rb +23 -0
  17. data/lib/roadforest/authorization/grants-holder.rb +58 -0
  18. data/lib/roadforest/authorization/manager.rb +85 -0
  19. data/lib/roadforest/authorization/policy.rb +19 -0
  20. data/lib/roadforest/graph/access-manager.rb +25 -2
  21. data/lib/roadforest/graph/focus-list.rb +4 -0
  22. data/lib/roadforest/graph/graph-focus.rb +30 -13
  23. data/lib/roadforest/graph/nav-affordance-builder.rb +62 -0
  24. data/lib/roadforest/graph/normalization.rb +3 -3
  25. data/lib/roadforest/graph/path-vocabulary.rb +64 -0
  26. data/lib/roadforest/graph/post-focus.rb +5 -0
  27. data/lib/roadforest/graph/vocabulary.rb +4 -1
  28. data/lib/roadforest/http/adapters/excon.rb +4 -0
  29. data/lib/roadforest/http/graph-transfer.rb +17 -1
  30. data/lib/roadforest/http/keychain.rb +121 -33
  31. data/lib/roadforest/http/user-agent.rb +5 -3
  32. data/lib/roadforest/interface/application.rb +25 -8
  33. data/lib/roadforest/interface/rdf.rb +114 -15
  34. data/lib/roadforest/interface/utility.rb +3 -0
  35. data/lib/roadforest/interface/utility/backfill.rb +63 -0
  36. data/lib/roadforest/interface/utility/grant-list.rb +45 -0
  37. data/lib/roadforest/interface/utility/grant.rb +22 -0
  38. data/lib/roadforest/interfaces.rb +1 -0
  39. data/lib/roadforest/path-matcher.rb +471 -0
  40. data/lib/roadforest/remote-host.rb +159 -35
  41. data/lib/roadforest/resource/read-only.rb +23 -4
  42. data/lib/roadforest/server.rb +32 -3
  43. data/lib/roadforest/source-rigor/graph-store.rb +0 -2
  44. data/lib/roadforest/source-rigor/rigorous-access.rb +138 -21
  45. data/lib/roadforest/templates/affordance-property-values.haml +3 -0
  46. data/lib/roadforest/templates/rdfpost-curie.haml +1 -1
  47. data/lib/roadforest/test-support/matchers.rb +41 -12
  48. data/lib/roadforest/test-support/remote-host.rb +3 -3
  49. data/lib/roadforest/type-handlers/rdfa-writer/environment-decorator.rb +1 -1
  50. data/lib/roadforest/type-handlers/rdfa-writer/render-engine.rb +40 -27
  51. data/lib/roadforest/type-handlers/rdfa.rb +10 -3
  52. data/lib/roadforest/utility/class-registry.rb +44 -4
  53. data/spec/affordance-augmenter.rb +46 -19
  54. data/spec/affordances-flow.rb +46 -30
  55. data/spec/authorization.rb +16 -4
  56. data/spec/client.rb +22 -4
  57. data/spec/focus-list.rb +24 -0
  58. data/spec/full-integration.rb +8 -3
  59. data/spec/graph-store.rb +8 -0
  60. data/spec/keychain.rb +18 -14
  61. data/spec/rdf-normalization.rb +32 -6
  62. data/spec/update-focus.rb +36 -39
  63. metadata +19 -5
@@ -3,6 +3,9 @@
3
3
  - objects.each do |object|
4
4
  - if object.is_subject?
5
5
  = rdfpost_curie("o", object.subject)
6
+ %label{}
7
+ %span= get_predicate_name(predicate)
8
+ %input{object.attrs.merge(:readonly => true)}
6
9
  - elsif object.attrs.empty?
7
10
  = yield(object)
8
11
  - else
@@ -1,5 +1,5 @@
1
1
  - if reduced?
2
- - unless prefix.empty?
2
+ - unless prefix.nil? or prefix.empty?
3
3
  %input{type: "hidden", name: "#{kind}n", value: prefix}
4
4
  %input{type: "hidden", name: "#{kind}v", value: suffix}
5
5
  - else
@@ -6,6 +6,10 @@ class RDF::Repository
6
6
  include RDF::Isomorphic
7
7
  end
8
8
 
9
+ class RDF::Graph
10
+ include RDF::Isomorphic
11
+ end
12
+
9
13
  module RoadForest
10
14
  module Testing
11
15
  module HelperMethods
@@ -13,6 +17,23 @@ module RoadForest
13
17
  StatementsFromGraph.new(graph)
14
18
  end
15
19
 
20
+ # Heuristically detect the input stream
21
+ def detect_format(stream)
22
+ # Got to look into the file to see
23
+ if stream.is_a?(IO) || stream.is_a?(StringIO)
24
+ stream.rewind
25
+ string = stream.read(1000)
26
+ stream.rewind
27
+ else
28
+ string = stream.to_s
29
+ end
30
+ case string
31
+ when /<html/i then RDF::RDFa::Reader
32
+ when /@prefix/i then RDF::Turtle::Reader
33
+ else RDF::NTriples::Reader
34
+ end
35
+ end
36
+
16
37
  def normalize(graph)
17
38
  case graph
18
39
  when RDF::Queryable then graph
@@ -22,7 +43,7 @@ module RoadForest
22
43
  # Figure out which parser to use
23
44
  g = RDF::Graph.new
24
45
  reader_class = detect_format(graph)
25
- reader_class.new(graph, :base_uri => @info.about).each {|s| g << s}
46
+ reader_class.new(graph, :base_uri => @info.nil? ? nil : @info.about).each {|s| g << s}
26
47
  g
27
48
  end
28
49
  end
@@ -72,7 +93,7 @@ module RoadForest
72
93
  "be equivalent to an expected graph" #graphs tend to be too long to use
73
94
  end
74
95
 
75
- def failure_message_for_should(actual)
96
+ def failure_message_for_should
76
97
  info = @info.respond_to?(:about) ? @info.about : @info.inspect
77
98
  if @expected.is_a?(RDF::Graph) && @actual.size != @expected.size
78
99
  "Graph entry count differs:\nexpected: #{@expected.size}\nactual: #{@actual.size}"
@@ -94,12 +115,18 @@ module RoadForest
94
115
  def initialize(xpath, value, trace)
95
116
  @xpath, @value, @trace = xpath, value, trace
96
117
  end
97
- attr_reader :xpath, :value, :trace
118
+ attr_reader :xpath, :value, :trace, :actual
119
+ attr_accessor :found
120
+
121
+ def description
122
+ "should match #{@xpath.inspect}"
123
+ end
98
124
 
99
125
  def matches?(actual)
126
+ @actual = actual
100
127
  @doc = Nokogiri::HTML.parse(actual)
101
128
  @namespaces = @doc.namespaces.merge("xhtml" => "http://www.w3.org/1999/xhtml", "xml" => "http://www.w3.org/XML/1998/namespace")
102
- found = @doc.root.at_xpath(xpath, @namespaces)
129
+ self.found = @doc.root.at_xpath(xpath, @namespaces)
103
130
  case value
104
131
  when false
105
132
  found.nil?
@@ -114,8 +141,7 @@ module RoadForest
114
141
  end
115
142
  end
116
143
 
117
- def failure_message_for_should(actual)
118
- trace ||= debug
144
+ def failure_message_for_should
119
145
  msg =
120
146
  case value
121
147
  when true
@@ -130,8 +156,7 @@ module RoadForest
130
156
  msg
131
157
  end
132
158
 
133
- def failure_message_for_should_not(actual)
134
- trace ||= debug
159
+ def failure_message_for_should_not
135
160
  msg = "expected that #{xpath.inspect} would not be #{value.inspect} in:\n" + actual.to_s
136
161
  msg += "\nDebug:#{trace.join("\n")}" if trace
137
162
  msg
@@ -176,13 +201,18 @@ module RoadForest
176
201
  not solutions.empty?
177
202
  end
178
203
 
204
+ def indent(string)
205
+ string.split("\n").map{|line| " " + line}.join("\n")
206
+ end
207
+
179
208
  def failure_message_for_should
180
- "expected #{@query.patterns.inspect} to return solutions on \n#{@actual.dump(:nquads)}\n but didn't"
209
+ require 'pp'
210
+ "expected: \n#{indent(@query.patterns.pretty_inspect)} \nto return solutions on \n\n#{indent(@actual.dump(:nquads))}\n but didn't"
181
211
  end
182
212
 
183
213
  def failure_message_for_should_not
184
- "expected #{@query.patterns.inspect} not to return solutions on \n#{@actual.dump(:nquads)}\n but does"
185
- end
214
+ require 'pp'
215
+ "expected: \n#{indent(@query.patterns.pretty_inspect)} \nnot to return solutions on \n\n#{indent(@actual.dump(:nquads))}\n but does" end
186
216
  end
187
217
 
188
218
  class ListEquivalence
@@ -191,7 +221,6 @@ module RoadForest
191
221
  end
192
222
 
193
223
  def subtract(one, other)
194
- sorted = one.sort_by{|stmt| stmt.to_a}
195
224
  one.find_all do |expected_stmt|
196
225
  not other.any? do |actual_stmt|
197
226
  actual_stmt.eql? expected_stmt
@@ -3,9 +3,9 @@ require 'roadforest/remote-host'
3
3
  require 'roadforest/test-support/http-client'
4
4
  module RoadForest::TestSupport
5
5
  class RemoteHost < ::RoadForest::RemoteHost
6
- def initialize(app)
7
- @app = app
8
- super(app.canonical_host)
6
+ def initialize(services)
7
+ @app = RoadForest::Application.new(services)
8
+ super(services.canonical_host)
9
9
  end
10
10
 
11
11
  def build_graph_store
@@ -264,7 +264,7 @@ module RoadForest
264
264
 
265
265
  def attrs
266
266
  _decorated_.attrs.merge(
267
- :method => "POST", :action => subject.join("put")
267
+ :method => "POST", :action => subject / "put"
268
268
  )
269
269
  end
270
270
  end
@@ -29,7 +29,8 @@ module RoadForest::TypeHandlers
29
29
  end.handle_templates do |config|
30
30
  #At some point, should look into using HTML entities to preserve
31
31
  #whitespace in XMLLiterals
32
- config.add_type("haml", { :template_cache => template_cache, :template_options => haml_options || {:ugly => true} })
32
+ options = {:format => :xhtml}.merge(haml_options || {:ugly => true})
33
+ config.add_type("haml", { :template_cache => template_cache, :template_options => options })
33
34
  end
34
35
  end
35
36
 
@@ -56,10 +57,12 @@ module RoadForest::TypeHandlers
56
57
  attr_accessor :prefixes, :base_uri, :lang, :standard_prefixes, :graph, :titles, :doc_title, :graph_name
57
58
  attr_accessor :template_handler
58
59
  attr_reader :debug
60
+ attr_accessor :debugging_comments
59
61
 
60
62
  attr_reader :decoration_set
61
63
 
62
64
  def initialize(graph, debug=nil)
65
+ @debugging_comments = false
63
66
  @debug = debug
64
67
  @graph = graph
65
68
  @graph_name = nil
@@ -104,11 +107,18 @@ module RoadForest::TypeHandlers
104
107
 
105
108
  def add_debug(message = nil)
106
109
  return unless ::RoadForest.debug_io || @debug
107
- message ||= ""
108
- message = message + yield if block_given?
109
- msg = "#{' ' * @debug_indent}#{message}"
110
- RoadForest::debug(msg)
111
- @debug << msg.force_encoding("utf-8") if @debug.is_a?(Array)
110
+ message ||= " " * @debug_indent
111
+ begin
112
+ message = message + yield if block_given?
113
+ rescue => ex
114
+ message += ex.inspect
115
+ message += "\n"
116
+ message += ex.backtrace[0...10].map do |line|
117
+ (" " * (@debug_indent + 1)) + line
118
+ end.join("\n")
119
+ end
120
+ RoadForest::debug(message)
121
+ @debug << message.force_encoding("utf-8") if @debug.is_a?(Array)
112
122
  end
113
123
 
114
124
  def setup
@@ -171,7 +181,6 @@ module RoadForest::TypeHandlers
171
181
  !seen.include?(s)
172
182
  end.each do |class_uri|
173
183
  graph.query(:predicate => RDF.type, :object => class_uri).map {|st| st.subject}.sort.uniq.each do |subject|
174
- #add_debug {"order_subjects: #{subject.inspect}"}
175
184
  subjects << subject
176
185
  seen[subject] = true
177
186
  end
@@ -184,9 +193,9 @@ module RoadForest::TypeHandlers
184
193
  [r.is_a?(RDF::Node) ? 1 : 0, ref_count(r), r]
185
194
  end.sort
186
195
 
187
- add_debug {"order_subjects: #{recursable.inspect}"}
188
-
189
196
  subjects += recursable.map{|r| r.last}
197
+ add_debug {"order_subjects: (final) \n #{subjects.join("\n ")}"}
198
+ return subjects
190
199
  end
191
200
 
192
201
  def order_properties(properties)
@@ -231,21 +240,21 @@ module RoadForest::TypeHandlers
231
240
  curie =
232
241
  case
233
242
  when @uri_to_term_or_curie.has_key?(uri)
234
- add_debug {"get_curie(#{uri}): uri_to_term_or_curie #{@uri_to_term_or_curie[uri].inspect}"}
243
+ add_debug {"get_curie(#{uri}): cached: #{@uri_to_term_or_curie[uri].inspect}"}
235
244
  return @uri_to_term_or_curie[uri]
236
245
  when base_uri && uri.index(base_uri.to_s) == 0
237
- add_debug {"get_curie(#{uri}): base_uri (#{uri.sub(base_uri.to_s, "")})"}
246
+ add_debug {"get_curie(#{uri}): base_uri: (#{base_uri} + #{uri.sub(base_uri.to_s, "")})"}
238
247
  uri.sub(base_uri.to_s, "")
239
248
  when @vocabulary && uri.index(@vocabulary) == 0
240
- add_debug {"get_curie(#{uri}): vocabulary"}
249
+ add_debug {"get_curie(#{uri}): vocabulary: #{@vocabulary.inspect}"}
241
250
  uri.sub(@vocabulary, "")
242
251
  when u = @uri_to_prefix.keys.detect {|u| uri.index(u.to_s) == 0}
243
- add_debug {"get_curie(#{uri}): uri_to_prefix"}
252
+ add_debug {"get_curie(#{uri}): uri_to_prefix: #{@uri_to_prefix[u]}"}
244
253
  prefix = @uri_to_prefix[u]
245
254
  @prefixes[prefix] = u
246
255
  uri.sub(u.to_s, "#{prefix}:")
247
256
  when @standard_prefixes && vocab = RDF::Vocabulary.detect {|v| uri.index(v.to_uri.to_s) == 0}
248
- add_debug {"get_curie(#{uri}): standard_prefixes"}
257
+ add_debug {"get_curie(#{uri}): standard_prefixes: #{vocab}"}
249
258
  prefix = vocab.__name__.to_s.split('::').last.downcase
250
259
  @prefixes[prefix] = vocab.to_uri
251
260
  uri.sub(vocab.to_uri.to_s, "#{prefix}:")
@@ -288,8 +297,6 @@ module RoadForest::TypeHandlers
288
297
  end
289
298
 
290
299
  def render(context)
291
- #puts "\n#{__FILE__.sub(/^#{Dir.pwd}/,'')}:#{__LINE__} =>
292
- ##{context.class.inspect}"
293
300
  add_debug "render"
294
301
  if context.render_checked
295
302
  return ""
@@ -297,11 +304,17 @@ module RoadForest::TypeHandlers
297
304
  template = find_environment_template(context)
298
305
  depth do
299
306
  add_debug{ "template: #{template.file}" }
307
+ add_debug{ "options: #{template.options}" }
300
308
  add_debug{ "context: #{context.class.name}"}
309
+ add_debug{ " #{context.attrs}" } if context.respond_to?(:attrs)
301
310
 
302
311
  begin
303
312
  @render_stack.push context
304
- template.render(context) do |item|
313
+ prefix = ""
314
+ if debugging_comments
315
+ prefix = "<!-- #{template.file} -->"
316
+ end
317
+ prefix + template.render(context) do |item|
305
318
  context.yielded(item)
306
319
  end.sub(/\n\Z/,'')
307
320
  ensure
@@ -311,7 +324,7 @@ module RoadForest::TypeHandlers
311
324
  end
312
325
 
313
326
  def is_list?(object)
314
- !(object == RDF.nil || (l = RDF::List.new(object, @graph)).invalid?)
327
+ !(object == RDF.nil || (RDF::List.new(object, @graph)).invalid?)
315
328
  end
316
329
 
317
330
  def subject_done(subject)
@@ -332,6 +345,15 @@ module RoadForest::TypeHandlers
332
345
  properties
333
346
  end
334
347
 
348
+ def build_env(klass)
349
+ env = klass.new(self)
350
+ env.heading_predicates = heading_predicates
351
+ env.lang = lang
352
+ env.parent = @render_stack.last
353
+ yield(env)
354
+ return decoration_set.decoration_for(env)
355
+ end
356
+
335
357
  def document_env
336
358
  build_env(DocumentEnvironment) do |env|
337
359
  env.subject_terms = @ordered_subjects
@@ -365,15 +387,6 @@ module RoadForest::TypeHandlers
365
387
  end
366
388
  end
367
389
 
368
- def build_env(klass)
369
- env = klass.new(self)
370
- env.heading_predicates = heading_predicates
371
- env.lang = lang
372
- env.parent = @render_stack.last
373
- yield(env)
374
- return decoration_set.decoration_for(env)
375
- end
376
-
377
390
  def object_env(predicate, object)
378
391
  subj = subject_env(object)
379
392
  unless subj.nil?
@@ -14,6 +14,7 @@ module RoadForest
14
14
  include Graph::Normalization
15
15
 
16
16
  attr_writer :valise, :tilt_cache
17
+ attr_accessor :haml_options
17
18
 
18
19
  def valise
19
20
  @valise ||= Valise.define do
@@ -33,9 +34,10 @@ module RoadForest
33
34
  templates = RDFaWriter::TemplateHandler.new
34
35
  templates.valise = valise
35
36
  templates.template_cache = tilt_cache
37
+ templates.haml_options = haml_options
36
38
 
37
39
  engine = RDFaWriter::RenderEngine.new(rdf, debug) do |engine|
38
- engine.graph_name = rdf.context
40
+ #engine.graph_name = nil #was: rdf.context
39
41
  engine.base_uri = base_uri
40
42
  engine.standard_prefixes = true
41
43
  engine.template_handler = templates
@@ -53,10 +55,15 @@ module RoadForest
53
55
  prefixes[prefix.to_sym] = prefixes[prefix]
54
56
  end
55
57
  engine.prefixes.merge! prefixes
56
-
57
- #$stderr.puts debug
58
+ engine.prefixes.keys.each do |key|
59
+ if key.is_a? String
60
+ engine.prefixes[key.to_sym] = engine.prefixes.delete(key)
61
+ end
62
+ end
58
63
 
59
64
  result = engine.render_document
65
+ #puts "\n#{__FILE__}:#{__LINE__} => \n#{debug.join("\n")}"
66
+ return result
60
67
  end
61
68
 
62
69
  def network_to_local(base_uri, source)
@@ -50,28 +50,68 @@ module RoadForest
50
50
  else
51
51
  @purpose = purpose
52
52
  end
53
+ @sequence = NameSequence.new
53
54
  @classes = {}
54
55
  end
55
56
 
57
+ require 'tsort'
58
+ class NameSequence
59
+ include TSort
60
+
61
+ def initialize
62
+ @nodes = Hash.new do |h,k|
63
+ h[k] = []
64
+ end
65
+ end
66
+
67
+ def add(before, after)
68
+ @nodes[before] << after
69
+ end
70
+
71
+ def exists(node)
72
+ @nodes[node] ||= []
73
+ end
74
+
75
+ def tsort_each_node(&block)
76
+ @nodes.each_key(&block)
77
+ end
78
+
79
+ def tsort_each_child(node, &block)
80
+ @nodes.fetch(node).each(&block)
81
+ end
82
+ end
83
+
84
+ # @yield each class in name order
56
85
  def map_classes
57
86
  names.map do |name|
58
- yield get(name)
87
+ begin
88
+ yield get(name)
89
+ rescue UndefinedClass
90
+ warn "undefined name: #{name} used in sequencing"
91
+ end
59
92
  end
60
93
  end
61
94
 
95
+ def names
96
+ @sequence.tsort
97
+ end
98
+
62
99
  def add(name, klass)
100
+ @sequence.exists(name.to_sym)
63
101
  @classes[name.to_sym] = klass
64
102
  @classes[name.to_s] = klass
65
103
  end
66
104
 
67
- def names
68
- @classes.keys.select{|key| key.is_a? Symbol}
105
+ def seq(before, after)
106
+ @sequence.add(before.to_sym, after.to_sym)
69
107
  end
70
108
 
109
+ class UndefinedClass < StandardError; end
110
+
71
111
  def get(name)
72
112
  @classes.fetch(name)
73
113
  rescue KeyError
74
- raise "No #@purpose class registered as name: #{name.inspect} (there are: #{names.inspect})"
114
+ raise UndefinedClass, "No #@purpose class registered as name: #{name.inspect} (there are: #{names.inspect})"
75
115
  end
76
116
  end
77
117
  end
@@ -4,7 +4,24 @@ require 'roadforest/application'
4
4
 
5
5
  describe RoadForest::Augment::Affordance do
6
6
  let :test_interface do
7
- Class.new(RoadForest::Interface::RDF)
7
+ Class.new(RoadForest::Interface::RDF) do |klass|
8
+ def update_payload
9
+ payload_pair do |root_node, graph|
10
+ seg1 = ::RDF::Node.new
11
+ graph << [ root_node, Path.forward, seg1 ]
12
+ graph << [ seg1, Path.predicate, EX.b ]
13
+ end
14
+ end
15
+
16
+ def create_payload
17
+ payload_pair do |root_node, graph|
18
+ seg1 = ::RDF::Node.new
19
+ graph << [ root_node, Path.forward, seg1 ]
20
+ graph << [ seg1, Path.predicate, EX.val ]
21
+ graph << [ seg1, Path.type, ::RDF::XSD.integer ]
22
+ end
23
+ end
24
+ end
8
25
  end
9
26
 
10
27
  let :other_test_interface do
@@ -12,11 +29,17 @@ describe RoadForest::Augment::Affordance do
12
29
  end
13
30
 
14
31
  Af = RoadForest::Graph::Af
32
+ Path = RoadForest::Graph::Path
15
33
 
16
34
  class EX < RDF::Vocabulary("http://example.com/"); end
17
35
 
18
36
  let :service_host do
19
- RoadForest::Application::ServicesHost.new
37
+ RoadForest::Application::ServicesHost.new.tap do |services|
38
+ services.root_url = "http://example.com/a"
39
+
40
+ services.router.add :test, ["a"], :parent, test_interface
41
+ services.router.add :nest, ["a", "b", :id], :leaf, other_test_interface
42
+ end
20
43
  end
21
44
 
22
45
  let :content_engine do
@@ -24,24 +47,11 @@ describe RoadForest::Augment::Affordance do
24
47
  end
25
48
 
26
49
  let :application do
27
- double("RoadForest::Application").tap do |app|
28
- app.stub(:services).and_return(service_host)
29
- app.stub(:default_content_engine).and_return(content_engine)
30
- end
31
- end
32
-
33
- let :router do
34
- RoadForest::Dispatcher.new(application).tap do |router|
35
- router.add :test, ["a"], :parent, test_interface
36
- router.add :nest, ["a", "b", :id], :leaf, other_test_interface
37
- end
50
+ RoadForest::Application.new(service_host)
38
51
  end
39
52
 
40
53
  let :augmenter do
41
- RoadForest::Augment::Augmenter.new.tap do |augmenter|
42
- augmenter.router = router
43
- augmenter.canonical_uri = Addressable::URI.parse("http://example.com/a")
44
- end
54
+ RoadForest::Augment::Augmenter.new(service_host)
45
55
  end
46
56
 
47
57
  subject :augmented_graph do
@@ -59,6 +69,9 @@ describe RoadForest::Augment::Affordance do
59
69
  subject.should match_query {
60
70
  pattern [:node, RDF.type, Af.Update]
61
71
  pattern [:node, Af.target, EX.a]
72
+ pattern [:node, Af.payload, :payload_root ]
73
+ pattern [:payload_root, Path.forward, :seg1 ]
74
+ pattern [:seg1, Path.predicate, EX.b ]
62
75
  }
63
76
  end
64
77
 
@@ -66,10 +79,24 @@ describe RoadForest::Augment::Affordance do
66
79
  subject.should match_query {
67
80
  pattern [:node, RDF.type, Af.Create]
68
81
  pattern [:node, Af.target, EX.a]
82
+ pattern [:node, Af.payload, :payload_root ]
83
+ pattern [:payload_root, Path.forward, :seg1 ]
84
+ pattern [:seg1, Path.predicate, EX.val ]
69
85
  }
70
86
  end
71
87
 
72
- it "should add Delete affordance"
73
- it "should add Navigable affordance to child"
88
+ it "should add Remove affordance" do
89
+ subject.should match_query {
90
+ pattern [:node, RDF.type, Af.Remove ]
91
+ pattern [:node, Af.target, EX.a ]
92
+ }
93
+ end
94
+
95
+ it "should add Navigate affordance to child" do
96
+ subject.should match_query {
97
+ pattern [:node, RDF.type, Af.Navigate ]
98
+ pattern [:node, Af.target, EX["a/b/1"] ]
99
+ }
100
+ end
74
101
  end
75
102
  end