roadforest 0.1 → 0.5

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 (120) hide show
  1. checksums.yaml +4 -4
  2. data/examples/file-management.rb +12 -13
  3. data/lib/roadforest-client.rb +3 -0
  4. data/lib/roadforest-common.rb +2 -0
  5. data/lib/roadforest-server.rb +7 -0
  6. data/lib/roadforest-testing.rb +1 -0
  7. data/lib/roadforest/application.rb +9 -7
  8. data/lib/roadforest/application/dispatcher.rb +39 -63
  9. data/lib/roadforest/application/parameters.rb +1 -1
  10. data/lib/roadforest/application/path-provider.rb +2 -2
  11. data/lib/roadforest/application/route-adapter.rb +130 -18
  12. data/lib/roadforest/application/services-host.rb +0 -4
  13. data/lib/roadforest/augment/affordance.rb +78 -0
  14. data/lib/roadforest/augment/augmentation.rb +97 -0
  15. data/lib/roadforest/augment/augmenter.rb +54 -0
  16. data/lib/roadforest/augmentations.rb +1 -0
  17. data/lib/roadforest/content-handling.rb +1 -0
  18. data/lib/roadforest/content-handling/common-engines.rb +67 -0
  19. data/lib/roadforest/content-handling/engine.rb +2 -14
  20. data/lib/roadforest/content-handling/handler-wrap.rb +29 -31
  21. data/lib/roadforest/content-handling/media-type.rb +6 -0
  22. data/lib/roadforest/{rdf.rb → graph.rb} +1 -1
  23. data/lib/roadforest/{rdf → graph}/access-manager.rb +12 -74
  24. data/lib/roadforest/{rdf → graph}/document.rb +1 -1
  25. data/lib/roadforest/{rdf → graph}/etagging.rb +2 -2
  26. data/lib/roadforest/{rdf → graph}/focus-list.rb +1 -9
  27. data/lib/roadforest/{rdf → graph}/graph-copier.rb +2 -2
  28. data/lib/roadforest/{rdf → graph}/graph-focus.rb +5 -7
  29. data/lib/roadforest/{rdf → graph}/normalization.rb +1 -1
  30. data/lib/roadforest/{rdf → graph}/post-focus.rb +2 -3
  31. data/lib/roadforest/graph/vocabulary.rb +96 -0
  32. data/lib/roadforest/http/graph-transfer.rb +2 -2
  33. data/lib/roadforest/interface/application.rb +145 -0
  34. data/lib/roadforest/interface/blob.rb +38 -0
  35. data/lib/roadforest/interface/rdf.rb +77 -0
  36. data/lib/roadforest/interfaces.rb +2 -0
  37. data/lib/roadforest/remote-host.rb +17 -17
  38. data/lib/roadforest/resource.rb +4 -0
  39. data/lib/roadforest/resource/{rdf/leaf-item.rb → leaf-item.rb} +1 -1
  40. data/lib/roadforest/resource/{rdf/list.rb → list.rb} +1 -1
  41. data/lib/roadforest/resource/{rdf/parent-item.rb → parent-item.rb} +1 -1
  42. data/lib/roadforest/resource/{rdf/read-only.rb → read-only.rb} +18 -18
  43. data/lib/roadforest/resource/role/has-children.rb +1 -1
  44. data/lib/roadforest/resource/role/writable.rb +2 -2
  45. data/lib/roadforest/server.rb +1 -1
  46. data/lib/roadforest/source-rigor.rb +9 -0
  47. data/lib/roadforest/{rdf/source-rigor → source-rigor}/credence-annealer.rb +2 -2
  48. data/lib/roadforest/{rdf/source-rigor → source-rigor}/credence.rb +5 -5
  49. data/lib/roadforest/{rdf/source-rigor → source-rigor}/credence/any.rb +1 -1
  50. data/lib/roadforest/{rdf/source-rigor → source-rigor}/credence/none-if-role-absent.rb +1 -1
  51. data/lib/roadforest/{rdf/source-rigor → source-rigor}/credence/role-if-available.rb +1 -1
  52. data/lib/roadforest/source-rigor/engine.rb +45 -0
  53. data/lib/roadforest/{rdf → source-rigor}/graph-store.rb +9 -9
  54. data/lib/roadforest/{rdf/source-rigor → source-rigor}/http-investigator.rb +2 -2
  55. data/lib/roadforest/{rdf → source-rigor}/investigation.rb +2 -2
  56. data/lib/roadforest/{rdf/source-rigor → source-rigor}/investigator.rb +3 -3
  57. data/lib/roadforest/{rdf/source-rigor → source-rigor}/null-investigator.rb +3 -2
  58. data/lib/roadforest/{rdf → source-rigor}/parcel.rb +5 -5
  59. data/lib/roadforest/{rdf → source-rigor}/resource-pattern.rb +6 -6
  60. data/lib/roadforest/{rdf → source-rigor}/resource-query.rb +2 -2
  61. data/lib/roadforest/source-rigor/rigorous-access.rb +101 -0
  62. data/lib/roadforest/templates/affordance-doc.haml +23 -0
  63. data/lib/roadforest/templates/affordance-property-values.haml +13 -0
  64. data/lib/roadforest/templates/affordance-subject.haml +9 -0
  65. data/lib/roadforest/templates/affordance-uri-object.haml +2 -0
  66. data/lib/roadforest/templates/base/{property_value.haml → property-value.haml} +0 -0
  67. data/lib/roadforest/templates/base/{property_values.haml → property-values.haml} +0 -0
  68. data/lib/roadforest/templates/distiller/{property_value.haml → property-value.haml} +0 -0
  69. data/lib/roadforest/templates/distiller/{property_values.haml → property-values.haml} +0 -0
  70. data/lib/roadforest/templates/min/{property_values.haml → property-values.haml} +0 -0
  71. data/lib/roadforest/templates/rdfpost-curie.haml +6 -0
  72. data/lib/roadforest/test-support/dispatcher-facade.rb +2 -0
  73. data/lib/roadforest/test-support/matchers.rb +169 -5
  74. data/lib/roadforest/test-support/remote-host.rb +2 -2
  75. data/lib/roadforest/type-handlers/handler.rb +74 -0
  76. data/lib/roadforest/type-handlers/jsonld.rb +34 -0
  77. data/lib/roadforest/type-handlers/rdf-handler.rb +36 -0
  78. data/lib/roadforest/{content-handling/type-handlers → type-handlers}/rdfa-writer.rb +2 -2
  79. data/lib/roadforest/{content-handling/type-handlers → type-handlers}/rdfa-writer/document-environment.rb +9 -8
  80. data/lib/roadforest/type-handlers/rdfa-writer/environment-decorator.rb +312 -0
  81. data/lib/roadforest/{content-handling/type-handlers → type-handlers}/rdfa-writer/object-environment.rb +3 -3
  82. data/lib/roadforest/{content-handling/type-handlers → type-handlers}/rdfa-writer/property-environment.rb +5 -11
  83. data/lib/roadforest/type-handlers/rdfa-writer/render-engine.rb +427 -0
  84. data/lib/roadforest/{content-handling/type-handlers → type-handlers}/rdfa-writer/render-environment.rb +33 -26
  85. data/lib/roadforest/{content-handling/type-handlers → type-handlers}/rdfa-writer/subject-environment.rb +7 -23
  86. data/lib/roadforest/type-handlers/rdfa.rb +73 -0
  87. data/lib/roadforest/type-handlers/rdfpost.rb +301 -0
  88. data/lib/roadforest/utility/class-registry.rb +23 -5
  89. data/spec/.ctrlp-root +0 -0
  90. data/spec/affordance-augmenter.rb +75 -0
  91. data/spec/affordances-flow.rb +438 -0
  92. data/spec/authorization.rb +34 -0
  93. data/spec/client.rb +13 -12
  94. data/spec/credence-annealer.rb +5 -5
  95. data/spec/focus-list.rb +8 -8
  96. data/spec/full-integration.rb +3 -3
  97. data/spec/graph-copier.rb +4 -4
  98. data/spec/graph-store.rb +19 -31
  99. data/spec/keychain.rb +82 -0
  100. data/spec/rdf-normalization.rb +2 -2
  101. data/spec/rdf-parcel.rb +3 -3
  102. data/spec/rdfa-handler.rb +514 -0
  103. data/spec/rdfpost.rb +96 -0
  104. data/spec/source-rigor.rb +57 -0
  105. data/spec/update-focus.rb +11 -10
  106. metadata +91 -66
  107. data/lib/roadforest/blob-model.rb +0 -53
  108. data/lib/roadforest/content-handling/type-handler.rb +0 -76
  109. data/lib/roadforest/content-handling/type-handlers/jsonld.rb +0 -36
  110. data/lib/roadforest/content-handling/type-handlers/rdf-handler.rb +0 -38
  111. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/render-engine.rb +0 -574
  112. data/lib/roadforest/content-handling/type-handlers/rdfa.rb +0 -175
  113. data/lib/roadforest/content-handling/type-handlers/rdfpost.rb +0 -297
  114. data/lib/roadforest/model.rb +0 -209
  115. data/lib/roadforest/models.rb +0 -2
  116. data/lib/roadforest/rdf/source-rigor.rb +0 -44
  117. data/lib/roadforest/rdf/vocabulary.rb +0 -11
  118. data/lib/roadforest/resource/http/form-parsing.rb +0 -81
  119. data/lib/roadforest/resource/rdf.rb +0 -4
  120. data/spec/form-parsing.rb +0 -1
@@ -1,14 +1,14 @@
1
1
  require 'rdf'
2
2
  require 'roadforest/debug'
3
- require 'roadforest/rdf/vocabulary'
4
- require 'roadforest/rdf/normalization'
3
+ require 'roadforest/graph/vocabulary'
4
+ require 'roadforest/graph/normalization'
5
5
 
6
- require 'roadforest/rdf/resource-query'
7
- require 'roadforest/rdf/resource-pattern'
6
+ require 'roadforest/source-rigor/resource-query'
7
+ require 'roadforest/source-rigor/resource-pattern'
8
8
 
9
- module RoadForest::RDF
10
- class GraphStore
11
- include Normalization
9
+ module RoadForest
10
+ class SourceRigor::GraphStore
11
+ include Graph::Normalization
12
12
 
13
13
  #The interface supported by ::RDF::Graph
14
14
  include ::RDF::Countable
@@ -183,7 +183,7 @@ module RoadForest::RDF
183
183
  def query_execute(query, &block)
184
184
  #XXX Weird edge case of GM getting queried with a vanilla RDF::Query...
185
185
  #needs tests, thought
186
- query = ResourceQuery.from(query)
186
+ query = RoadForest::SourceRigor::ResourceQuery.from(query)
187
187
  query.execute(self).filter do |solution|
188
188
  solution.respond_to?(:context) and not solution.context.nil?
189
189
  end.each(&block)
@@ -191,7 +191,7 @@ module RoadForest::RDF
191
191
 
192
192
  def query_pattern(pattern, &block)
193
193
  case pattern
194
- when ResourcePattern
194
+ when RoadForest::SourceRigor::ResourcePattern
195
195
  pattern.execute(@repository, {}, :context_roles => {:local => local_context_node}) do |statement|
196
196
  next if statement.context.nil?
197
197
  yield statement if block_given?
@@ -1,6 +1,6 @@
1
- require 'roadforest/rdf/source-rigor/investigator'
1
+ require 'roadforest/source-rigor/investigator'
2
2
  module RoadForest
3
- class RDF::SourceRigor
3
+ module SourceRigor
4
4
  class HTTPInvestigator < Investigator
5
5
  register :http
6
6
 
@@ -1,6 +1,6 @@
1
- require 'roadforest/rdf'
1
+ require 'roadforest/graph'
2
2
 
3
- module RoadForest::RDF
3
+ module RoadForest::SourceRigor
4
4
  class Investigation
5
5
  attr_accessor :context_roles, :queryable, :results, :source_rigor
6
6
 
@@ -1,6 +1,6 @@
1
1
  require 'roadforest/utility/class-registry'
2
2
 
3
- class RoadForest::RDF::SourceRigor
3
+ module RoadForest::SourceRigor
4
4
  class NotCredible < StandardError; end
5
5
  class NoCredibleResults < StandardError; end
6
6
 
@@ -13,5 +13,5 @@ class RoadForest::RDF::SourceRigor
13
13
  end
14
14
  end
15
15
  end
16
- require 'roadforest/rdf/source-rigor/null-investigator'
17
- require 'roadforest/rdf/source-rigor/http-investigator'
16
+ require 'roadforest/source-rigor/null-investigator'
17
+ require 'roadforest/source-rigor/http-investigator'
@@ -1,5 +1,6 @@
1
- require 'roadforest/rdf/source-rigor/investigator'
2
- class RoadForest::RDF::SourceRigor
1
+ require 'roadforest/source-rigor/investigator'
2
+
3
+ module RoadForest::SourceRigor
3
4
  class NullInvestigator < Investigator
4
5
  register :null
5
6
 
@@ -1,9 +1,9 @@
1
- require 'roadforest/rdf'
2
- require 'roadforest/rdf/normalization'
1
+ require 'roadforest/graph'
2
+ require 'roadforest/graph/normalization'
3
3
 
4
- module RoadForest::RDF
5
- class Parcel
6
- include Normalization
4
+ module RoadForest
5
+ class SourceRigor::Parcel
6
+ include Graph::Normalization
7
7
 
8
8
  attr_accessor :graph
9
9
 
@@ -1,9 +1,9 @@
1
1
  require 'rdf/query/pattern'
2
- require 'roadforest/rdf'
3
- require 'roadforest/rdf/graph-store'
4
- require 'roadforest/rdf/investigation'
2
+ require 'roadforest/graph'
3
+ require 'roadforest/source-rigor/graph-store'
4
+ require 'roadforest/source-rigor/investigation'
5
5
 
6
- module RoadForest::RDF
6
+ module RoadForest::SourceRigor
7
7
  class ResourcePattern < ::RDF::Query::Pattern
8
8
  def self.from(pattern, options)
9
9
  pattern = case pattern
@@ -19,7 +19,7 @@ module RoadForest::RDF
19
19
  options ||= {}
20
20
  self.new(options.merge(pattern))
21
21
  else
22
- raise ArgumentError, "expected RoadForest::RDF::ResourcePattern, RDF::Query::Pattern, RDF::Statement, Hash, or Array, but got #{pattern.inspect}"
22
+ raise ArgumentError, "expected RoadForest::SourceRigor::ResourcePattern, RDF::Query::Pattern, RDF::Statement, Hash, or Array, but got #{pattern.inspect}"
23
23
  end
24
24
 
25
25
  unless options.nil?
@@ -35,7 +35,7 @@ module RoadForest::RDF
35
35
  attr_accessor :context_roles, :source_rigor
36
36
 
37
37
  def execute(queryable, bindings = nil, query_context_roles = nil, &block)
38
- unless queryable.is_a? RoadForest::RDF::GraphStore
38
+ unless queryable.is_a? RoadForest::SourceRigor::GraphStore
39
39
  return super(queryable, bindings || {}, &block)
40
40
  end
41
41
 
@@ -1,7 +1,7 @@
1
- require 'roadforest/rdf'
1
+ require 'roadforest/graph'
2
2
  require 'rdf/query'
3
3
 
4
- module RoadForest::RDF
4
+ module RoadForest::SourceRigor
5
5
  class ResourceQuery < ::RDF::Query
6
6
  def initialize(patterns = [], options = {}, &block)
7
7
  @subject_context = options[:subject_context]
@@ -0,0 +1,101 @@
1
+ require 'roadforest/graph/access-manager'
2
+ require 'roadforest/source-rigor/resource-query'
3
+ require 'roadforest/source-rigor/resource-pattern'
4
+ require 'roadforest/source-rigor/parcel'
5
+
6
+ module RoadForest
7
+ module SourceRigor
8
+ module Rigorous
9
+ attr_accessor :rigor
10
+
11
+ def dup
12
+ other = self.class.allocate
13
+ other.resource = self.resource
14
+ other.rigor = self.rigor
15
+ other.source_graph = self.source_graph
16
+
17
+ return other
18
+ end
19
+
20
+ def build_query
21
+ ResourceQuery.new([], {}) do |query|
22
+ query.subject_context = resource
23
+ query.source_rigor = rigor
24
+ yield query
25
+ end
26
+ end
27
+
28
+ def query_execute(query, &block)
29
+ query = ResourceQuery.from(query, resource, rigor)
30
+ execute_search(query, &block)
31
+ end
32
+
33
+ def query_pattern(pattern, &block)
34
+ pattern = ResourcePattern.from(pattern, {:context_roles => {:subject => resource}, :source_rigor => rigor})
35
+ execute_search(pattern, &block)
36
+ end
37
+ end
38
+
39
+ class RetrieveManager < Graph::ReadOnlyManager
40
+ include Rigorous
41
+ end
42
+
43
+ class PostManager < Graph::WriteManager
44
+ include Rigorous
45
+ end
46
+
47
+ class UpdateManager < Graph::SplitManager
48
+ include Rigorous
49
+
50
+ def initialize
51
+ @copied_contexts = {}
52
+ end
53
+
54
+ attr_accessor :copied_contexts
55
+
56
+ def dup
57
+ other = super
58
+ other.copied_contexts = self.copied_contexts
59
+ other.target_graph = self.target_graph
60
+ return other
61
+ end
62
+
63
+ def execute_search(search, &block)
64
+ enum = search.execute(destination_graph)
65
+ if enum.any?{ true }
66
+ enum.each(&block)
67
+ return enum
68
+ end
69
+ search.execute(origin_graph, &block)
70
+ end
71
+
72
+ def insert(statement)
73
+ copy_context
74
+ super
75
+ end
76
+
77
+ def delete(statement)
78
+ copy_context
79
+ super
80
+ end
81
+
82
+ def parceller
83
+ @parceller ||=
84
+ begin
85
+ parceller = Parcel.new
86
+ parceller.graph = source_graph
87
+ parceller
88
+ end
89
+ end
90
+
91
+ def copy_context
92
+ return if copied_contexts[resource]
93
+ parceller.graph_for(resource).each_statement do |statement|
94
+ statement.context = resource
95
+ destination_graph << statement
96
+ end
97
+ copied_contexts[resource] = true
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,23 @@
1
+ !!! XML
2
+ !!! 5
3
+ %html{:xmlns => "http://www.w3.org/1999/xhtml", :lang => lang, :prefix => prefix}
4
+ - if base || title
5
+ %head
6
+ - if base
7
+ %base{:href => base}
8
+ - if title
9
+ %title= title
10
+ %body
11
+ - subjects.each do |subject|
12
+ - if subject.respond_to? :affordance?
13
+ %form{subject.attrs}
14
+ %input{type: "hidden", name: "rdf"}
15
+ - prefixes.each do |name, target|
16
+ - unless name.nil? or name.empty?
17
+ %input{type: "hidden", name: "n", value: name}
18
+ %input{type: "hidden", name: "v", value: target}
19
+
20
+ != yield(subject)
21
+ - else
22
+ %div{subject.attrs}
23
+ != yield(subject)
@@ -0,0 +1,13 @@
1
+ %div.property
2
+ = rdfpost_curie("p", predicate)
3
+ - objects.each do |object|
4
+ - if object.is_subject?
5
+ = rdfpost_curie("o", object.subject)
6
+ - elsif object.attrs.empty?
7
+ = yield(object)
8
+ - else
9
+ %label{object.label_attrs}
10
+ %span= get_predicate_name(predicate)
11
+ %input{object.input_attrs(yield(object))}
12
+ - if(object.type_uri)
13
+ %input{type: "hidden", name: "lt", value: object.type_uri}
@@ -0,0 +1,9 @@
1
+ - if typeof
2
+ %span.type!= typeof
3
+
4
+ = rdfpost_curie("s", subject)
5
+
6
+ - predicates.each do |predicate|
7
+ != yield(predicate)
8
+ - predicate_nodes.each do |subject|
9
+ %div{subject.attrs}= yield subject
@@ -0,0 +1,2 @@
1
+ = rdfpost_curie("o", object)
2
+ %a{:property => get_curie(predicate), :href => object.to_s, :inlist => inlist}= object.to_s
@@ -0,0 +1,6 @@
1
+ - if reduced?
2
+ - unless prefix.empty?
3
+ %input{type: "hidden", name: "#{kind}n", value: prefix}
4
+ %input{type: "hidden", name: "#{kind}v", value: suffix}
5
+ - else
6
+ %input{type: "hidden", name: "#{kind}u", value: uri}
@@ -3,6 +3,8 @@ require 'webmachine/headers'
3
3
  require 'webmachine/request'
4
4
  require 'webmachine/response'
5
5
  require 'webmachine/decision/flow'
6
+ require 'webmachine/decision/fsm'
7
+
6
8
  module RoadForest
7
9
  module TestSupport
8
10
  class DispatcherFacade < BasicObject
@@ -1,7 +1,165 @@
1
+ require 'rdf/isomorphic'
2
+ require 'rspec/matchers'
3
+ require 'nokogiri'
4
+
5
+ class RDF::Repository
6
+ include RDF::Isomorphic
7
+ end
8
+
1
9
  module RoadForest
2
10
  module Testing
11
+ module HelperMethods
12
+ def statements_from_graph(graph)
13
+ StatementsFromGraph.new(graph)
14
+ end
15
+
16
+ def normalize(graph)
17
+ case graph
18
+ when RDF::Queryable then graph
19
+ when IO, StringIO
20
+ RDF::Graph.new.load(graph, :base_uri => @info.about)
21
+ else
22
+ # Figure out which parser to use
23
+ g = RDF::Graph.new
24
+ reader_class = detect_format(graph)
25
+ reader_class.new(graph, :base_uri => @info.about).each {|s| g << s}
26
+ g
27
+ end
28
+ end
29
+ end
30
+
31
+ class BeEquivalentGraph
32
+ include HelperMethods
33
+ Info = Struct.new(:about, :num, :trace, :compare, :inputDocument, :outputDocument, :expectedResults, :format, :title)
34
+
35
+ def initialize(expected, info)
36
+ @expected = normalize(expected)
37
+
38
+ @info =
39
+ if info.respond_to?(:about)
40
+ info
41
+ elsif info.is_a?(Hash)
42
+ identifier = expected.is_a?(RDF::Graph) ? expected.context : info[:about]
43
+ trace = info[:trace]
44
+ trace = trace.join("\n") if trace.is_a?(Array)
45
+ i = Info.new(identifier, "0000", trace, info[:compare])
46
+ i.format = info[:format]
47
+ i
48
+ else
49
+ Info.new(expected.is_a?(RDF::Graph) ? expected.context : info, "0000", info.to_s)
50
+ end
51
+
52
+ @info.format ||= :ttl
53
+ end
54
+ attr_reader :expected, :info
55
+
56
+ def matches?(actual)
57
+ @actual = normalize(actual)
58
+ @actual.isomorphic_with?(@expected)# rescue false
59
+ end
60
+
61
+ def dump_graph(graph)
62
+ graph.dump(@info.format, :standard_prefixes => true)
63
+ rescue
64
+ begin
65
+ graph.dump(:nquads, :standard_prefixes => true)
66
+ rescue
67
+ graph.inspect
68
+ end
69
+ end
70
+
71
+ def description
72
+ "be equivalent to an expected graph" #graphs tend to be too long to use
73
+ end
74
+
75
+ def failure_message_for_should(actual)
76
+ info = @info.respond_to?(:about) ? @info.about : @info.inspect
77
+ if @expected.is_a?(RDF::Graph) && @actual.size != @expected.size
78
+ "Graph entry count differs:\nexpected: #{@expected.size}\nactual: #{@actual.size}"
79
+ elsif @expected.is_a?(Array) && @actual.size != @expected.length
80
+ "Graph entry count differs:\nexpected: #{@expected.length}\nactual: #{@actual.size}"
81
+ else
82
+ "Graph differs"
83
+ end +
84
+ "\n#{info + "\n" unless info.to_s.empty?}" +
85
+ (@info.inputDocument ? "Input file: #{@info.inputDocument}\n" : "") +
86
+ (@info.outputDocument ? "Output file: #{@info.outputDocument}\n" : "") +
87
+ "\nExpected:\n#{dump_graph(@expected)}" +
88
+ "\nResults:\n#{dump_graph(@actual)}" +
89
+ (@info.trace ? "\nDebug:\n#{@info.trace}" : "")
90
+ end
91
+ end
92
+
93
+ class HaveXpath
94
+ def initialize(xpath, value, trace)
95
+ @xpath, @value, @trace = xpath, value, trace
96
+ end
97
+ attr_reader :xpath, :value, :trace
98
+
99
+ def matches?(actual)
100
+ @doc = Nokogiri::HTML.parse(actual)
101
+ @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)
103
+ case value
104
+ when false
105
+ found.nil?
106
+ when true
107
+ !found.nil?
108
+ when Array
109
+ found.to_s.split(" ").include?(*value)
110
+ when Regexp
111
+ found.to_s =~ value
112
+ else
113
+ found.to_s == value
114
+ end
115
+ end
116
+
117
+ def failure_message_for_should(actual)
118
+ trace ||= debug
119
+ msg =
120
+ case value
121
+ when true
122
+ "expected that #{xpath.inspect} would be present\nwas:\n #{found.inspect}\n"
123
+ when false
124
+ "expected that #{xpath.inspect} would be absent\nwas:\n #{found.inspect}\n"
125
+ else
126
+ "expected that #{xpath.inspect} would be\n #{value.inspect}\nwas:\n #{found.inspect}\n"
127
+ end
128
+ msg += "in:\n" + actual.to_s
129
+ msg += "\nDebug:#{trace.join("\n")}" if trace
130
+ msg
131
+ end
132
+
133
+ def failure_message_for_should_not(actual)
134
+ trace ||= debug
135
+ msg = "expected that #{xpath.inspect} would not be #{value.inspect} in:\n" + actual.to_s
136
+ msg += "\nDebug:#{trace.join("\n")}" if trace
137
+ msg
138
+ end
139
+ end
140
+
141
+ class Produces
142
+ def initialize(expected, info)
143
+ @expected, @info = expected, info
144
+ end
145
+ attr_reader :expected, :info
146
+
147
+ def matches?(actual)
148
+ actual == expected
149
+ end
150
+
151
+ def failure_message_for_should(actual)
152
+ "Expected: #{expected.inspect}\n" +
153
+ "Actual : #{actual.inspect}\n" +
154
+ "Processing results:\n#{info.join("\n")}"
155
+ end
156
+ end
157
+
3
158
  class MatchesQuery
4
159
  def initialize(pattern = nil, &block)
160
+ if pattern.nil? and block.nil?
161
+ raise "Matches query (e.g. should match_query) created with no patterns: probably used a do block..."
162
+ end
5
163
  pattern ||= []
6
164
  if Hash === pattern
7
165
  pattern = [pattern]
@@ -74,17 +232,23 @@ module RoadForest
74
232
  alias that_match_pattern that_match_query
75
233
  end
76
234
 
77
- module HelperMethods
78
- def statements_from_graph(graph)
79
- StatementsFromGraph.new(graph)
235
+ module MatcherMethods
236
+ def produce(expected, info)
237
+ Produces.new(expected, info)
238
+ end
239
+
240
+ def have_xpath(xpath, value = true, trace = nil)
241
+ HaveXpath.new(xpath, value, trace || debug)
80
242
  end
81
- end
82
243
 
83
- module MatcherMethods
84
244
  def match_query(pattern = nil, &block)
85
245
  MatchesQuery.new(pattern, &block)
86
246
  end
87
247
 
248
+ def be_equivalent_graph(graph, info = nil)
249
+ BeEquivalentGraph.new(graph, info)
250
+ end
251
+
88
252
  def be_equivalent_to(list)
89
253
  ListEquivalence.new(list)
90
254
  end