sawtooth 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,102 @@
1
+ require 'test_helper'
2
+
3
+ class Sawtooth::BuilderTest < MiniTest::Unit::TestCase
4
+
5
+ def test_using_basic_builder
6
+ @builder = Sawtooth::Builder.new do
7
+ before { |doc| doc << Array.new }
8
+ after { |doc| doc << doc.pop.first }
9
+
10
+ on('statuses/status') do
11
+ on_start { |doc| doc << Hash.new }
12
+ on_finish { |doc| doc.parent << doc.pop }
13
+ end
14
+
15
+ on_text('statuses/status/created_at' => :created_at) { |str| Date.parse(str) }
16
+ on_text 'statuses/status/text' => :value
17
+ on_text 'statuses/status/*' => Proc.new { |str| str.to_sym }
18
+ end
19
+
20
+ @doc = @builder.parse File.read(fixture_path('statuses.xml'))
21
+ assert_equal 'I so just thought the guy lighting the Olympic torch was falling when he began to run on the wall. Wow that would have been catastrophic.', @doc.root[:value]
22
+ assert_equal '2008-08-09', @doc.root[:created_at].strftime('%Y-%m-%d')
23
+ assert_nil @doc.root[:screen_name]
24
+ assert_equal 'web', @doc.root[:source]
25
+ end
26
+
27
+ def test_delegate_shortcut
28
+ user = Sawtooth::Builder.new do
29
+ before { |doc| doc << Hash.new }
30
+ after { |doc| doc.parent['user'] = doc.pop }
31
+
32
+ on_text('user/name')
33
+ on_text('user/screen_name')
34
+ on_text('user/id') { |str| str.to_i }
35
+ end
36
+
37
+ builder = Sawtooth::Builder.new do
38
+ before { |doc| doc << [] }
39
+ after { |doc| doc << doc.pop.last }
40
+
41
+ on('statuses/status') do
42
+ on_start { |doc| doc << Hash.new }
43
+ on_finish { |doc| doc.parent << doc.pop }
44
+ end
45
+
46
+ on_text('statuses/status/text')
47
+ delegate('statuses/status/user/**' => user)
48
+ end
49
+
50
+ @doc = builder.parse File.read(fixture_path('statuses.xml'))
51
+ assert_match /^Netshare will no longer start up for me\./, @doc.root['text']
52
+ assert_equal 'John Nunemaker', @doc.root['user']['name']
53
+ assert_equal 4243, @doc.root['user']['id']
54
+ end
55
+
56
+ def test_chained_delegate_rules
57
+
58
+ order = []
59
+
60
+ block = Sawtooth::Builder.new do
61
+ on_text('Blocks/Title' => 'title', 'Blocks/Text' => 'text')
62
+ after { order << "block" }
63
+ end
64
+
65
+ article = Sawtooth::Builder.new do
66
+ before { |doc| doc << Hash.new }
67
+ after { |doc| order << "article"; doc.parent == doc.root ? doc.parent['sections'].first << doc.pop : doc.parent << doc.pop }
68
+
69
+ delegate('Blocks/**' => block)
70
+ end
71
+
72
+ section = Sawtooth::Builder.new do
73
+ before { |doc| doc << [] }
74
+ after { |doc| order << "section"; doc.parent['sections'] << doc.pop }
75
+
76
+ delegate('Article/**' => article, :prefix => 'Article')
77
+ end
78
+
79
+ builder = Sawtooth::Builder.new do
80
+ before { |doc| doc.push('sections' => [[]]) }
81
+ after { |doc| order << "builder" }
82
+
83
+ on_text('Articles/Author')
84
+ on_text('Articles/Version') { |str| str.to_i }
85
+
86
+ delegate('Articles/MainArticle/**' => article, :prefix => 'Articles/MainArticle')
87
+ delegate('Articles/Section/**' => section, :prefix => 'Articles/Section')
88
+ end
89
+
90
+ @doc = builder.parse File.read(fixture_path('delegate.xml'))
91
+ assert_equal 'lukas', @doc.root['author']
92
+ assert_equal 35, @doc.root['version']
93
+
94
+ assert_equal 1, @doc.stack.size
95
+ assert_equal 2, @doc.root['sections'].size
96
+
97
+ assert_equal 'Didum', @doc.root['sections'].last.first['title']
98
+ assert_equal 'Barfoo', @doc.root['sections'].first.first['text']
99
+
100
+ assert_equal %w{block article block article section block article block article builder}, order
101
+ end
102
+ end
@@ -0,0 +1,119 @@
1
+ require 'test_helper'
2
+
3
+ class Sawtooth::DocumentTest < MiniTest::Unit::TestCase
4
+
5
+ # A fake Attribute, for testing
6
+ FakeAttr = Struct.new(:localname, :value) do
7
+ def self.build(hsh = {})
8
+ hsh.map { |k,v| self.new(k, v) }
9
+ end
10
+ end
11
+
12
+ # A fake delegate for testing
13
+ class FakeDelegate
14
+ attr_reader :args
15
+ def path; @args[0] end
16
+ def doc; @args[1] end
17
+ def node; @args[2] end
18
+ def start_document(*args); @args = args end
19
+ def end_document(*args); @args = args.dup end
20
+ def start_element(*args); @args = args end
21
+ def end_element(*args); @args = args.map { |e| e.dup } end
22
+ end
23
+
24
+ def setup
25
+ @delegate = FakeDelegate.new
26
+ @doc = Sawtooth::Document.new @delegate
27
+ end
28
+
29
+ def test_that_elements_can_be_pushed_onto_the_stack
30
+ @doc.push "a"
31
+ @doc.push "b"
32
+ assert_equal %w{a b}, @doc.stack
33
+ end
34
+
35
+ def test_elements_can_be_pushed_using_lshift
36
+ @doc << "a"
37
+ @doc << "b"
38
+ assert_equal %w{a b}, @doc.stack
39
+ end
40
+
41
+ def test_push_chaining
42
+ @doc.push("a").push("b") << "c" << "d"
43
+ assert_equal %w{a b c d}, @doc.stack
44
+ end
45
+
46
+ def test_that_elements_can_be_popped_from_the_stack
47
+ @doc << "a" << "b"
48
+ @doc.pop
49
+ assert_equal %w{a}, @doc.stack
50
+ end
51
+
52
+ def test_that_pop_returns_popped_item
53
+ @doc.push("a").push("b").push("c")
54
+ assert_equal "c", @doc.pop
55
+ assert_equal "b", @doc.pop
56
+ assert_equal %w{a}, @doc.stack
57
+ end
58
+
59
+ def test_that_peek_looks_at_the_element
60
+ @doc << "a" << "b" << "c"
61
+ assert_equal "c", @doc.peek
62
+ assert_equal "b", @doc.peek(1)
63
+ assert_equal "a", @doc.peek(2)
64
+ assert_nil @doc.peek(3)
65
+ end
66
+
67
+ def test_current_and_parent_peek_aliases
68
+ @doc << "a" << "b" << "c"
69
+ assert_equal "c", @doc.current
70
+ assert_equal "b", @doc.parent
71
+ end
72
+
73
+ def test_root_method
74
+ @doc << "a"
75
+ assert_equal "a", @doc.root
76
+ @doc << "b"
77
+ assert_equal "a", @doc.root
78
+ end
79
+
80
+ def test_document_parsing
81
+ @doc.start_document
82
+ assert_equal 0, @doc.path.size
83
+ assert_equal 1, @delegate.path.size
84
+ assert_equal '@document', @delegate.path.first.name
85
+
86
+ # <root type='array'>
87
+ @doc.start_element_namespace 'root', FakeAttr.build({ 'type' => 'array' })
88
+ assert_equal 1, @doc.path.size
89
+ assert_equal 'root', @delegate.node.name
90
+
91
+ # <root type='array'>
92
+ # <elem>
93
+ @doc.start_element_namespace 'elem'
94
+ assert_equal 2, @doc.path.size
95
+ assert_equal "root/elem", @doc.path.join('/')
96
+
97
+ # text
98
+ @doc.characters(" te")
99
+ @doc.characters("xt\n ")
100
+
101
+ # </elem>
102
+ @doc.end_element_namespace 'elem'
103
+ assert_equal 1, @doc.path.size
104
+ assert_equal 'elem', @delegate.node.name
105
+ assert_equal 'text', @delegate.node.text
106
+
107
+ # </root>
108
+ @doc.end_element_namespace 'root'
109
+ assert_equal 0, @doc.path.size
110
+ assert_equal 1, @delegate.path.size
111
+ assert_equal 'root', @delegate.node.name
112
+ assert_equal({ 'type' => 'array' }, @delegate.node.attributes)
113
+
114
+ # end document
115
+ @doc.end_document
116
+ assert_equal 1, @delegate.path.size
117
+ assert_equal '@document', @delegate.path.first.name
118
+ end
119
+ end
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+
3
+ class Sawtooth::DelegateTest < MiniTest::Unit::TestCase
4
+ def setup
5
+ @parser = Sawtooth::Parser.new
6
+ @initRule = Sawtooth::Rules::CallRule.new(:start => Proc.new { |doc| doc << Array.new })
7
+ @addRule = Sawtooth::Rules::TextRule.new
8
+ end
9
+
10
+ def test_adding_simple_rule_and_parsing_file
11
+ @parser.add("statuses", @initRule)
12
+ @parser.add("statuses/status/text", @addRule)
13
+ doc = @parser.parse File.open(fixture_path('statuses.xml'))
14
+ assert_equal 'I so just thought the guy lighting the Olympic torch was falling when he began to run on the wall. Wow that would have been catastrophic.', doc.peek.first
15
+ assert_equal 20, doc.peek.size
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+ require 'open-uri'
3
+
4
+ class Sawtooth::ReadmeTest < MiniTest::Unit::TestCase
5
+ def test_primary_cnn_example
6
+ rules = Sawtooth.rules do
7
+ before { |doc| doc << [] }
8
+ on 'rss/channel/item' do
9
+ on_start { |doc| doc << Hash.new }
10
+ on_finish { |doc| doc.parent << doc.pop }
11
+ end
12
+ on_text 'rss/channel/item/*'
13
+ end
14
+
15
+ result = rules.parse(open('http://rss.cnn.com/rss/edition.rss')).root
16
+
17
+ assert_instance_of Array, result
18
+ assert_instance_of Hash, result.first
19
+ assert_equal %w{guid title pub_date description link}.sort, result.first.keys.sort
20
+ end
21
+ end
@@ -0,0 +1,44 @@
1
+ require 'test_helper'
2
+
3
+ class Sawtooth::Rules::DelegateRuleTest < MiniTest::Unit::TestCase
4
+
5
+ include Sawtooth::Rules
6
+
7
+ XML = '<didum><del><foo><bar>x</bar><baz>z</baz></foo></del><da>123</da></didum>'
8
+
9
+ def setup
10
+ @parser = Sawtooth::Parser.new
11
+ @parser.add("didum", CallRule.new(:start => Proc.new { |doc| doc << Hash.new }))
12
+ @parser.add("didum/da", TextRule.new)
13
+ end
14
+
15
+ def test_using_delgate_rule
16
+ @rules = Sawtooth::Rules::Set.new
17
+ @rules.add("@document:before", CallRule.new(:start => Proc.new { |doc| doc << Hash.new }))
18
+ @rules.add("@document:after", CallRule.new(:finish => Proc.new { |doc| doc.parent['del'] = doc.pop }))
19
+ @rules.add("foo/bar", TextRule.new)
20
+ @rules.add("foo/baz", TextRule.new)
21
+
22
+ @rule = Sawtooth::Rules::DelegateRule.new :prefix => "didum/del/", :rules => @rules
23
+ @parser.add('didum/del', @rule.before_after_callbacks_rule)
24
+ @parser.add('didum/del/**', @rule)
25
+ obj = @parser.parse(XML).top
26
+ assert_equal '123', obj['da']
27
+ assert_equal({ 'baz' => 'z', 'bar' => 'x' }, obj['del'])
28
+ end
29
+
30
+ def test_using_prefix_delegate_rule
31
+ @rules = Sawtooth::Rules::Set.new
32
+ @rules.add("@document:before", CallRule.new(:start => Proc.new { |doc| doc << Hash.new }))
33
+ @rules.add("@document:after", CallRule.new(:finish => Proc.new { |doc| doc.parent['del'] = doc.pop }))
34
+ @rules.add("bar", TextRule.new)
35
+ @rules.add("baz", TextRule.new)
36
+
37
+ @rule = Sawtooth::Rules::DelegateRule.new :prefix => "didum/del/foo", :rules => @rules
38
+ @parser.add('didum/del/foo', @rule.before_after_callbacks_rule)
39
+ @parser.add('didum/del/foo/**', @rule)
40
+ obj = @parser.parse(XML).top
41
+ assert_equal '123', obj['da']
42
+ assert_equal({ 'baz' => 'z', 'bar' => 'x' }, obj['del'])
43
+ end
44
+ end
@@ -0,0 +1,59 @@
1
+ require 'test_helper'
2
+
3
+ class Sawtooth::Rules::TextRuleTest < MiniTest::Unit::TestCase
4
+
5
+ # Test Class
6
+ SomeModel = Struct.new(:first_name)
7
+
8
+ def test_setting_value_open_model
9
+ doc.push SomeModel.new
10
+ rule = Sawtooth::Rules::TextRule.new
11
+ rule.finish("root/firstName", doc, build_node!("firstName", :text => "Hans"))
12
+ assert_equal "Hans", doc.top.first_name
13
+ end
14
+
15
+ def test_setting_value_to_hash
16
+ doc.push Hash.new
17
+ rule = Sawtooth::Rules::TextRule.new
18
+ rule.finish("root/firstName", doc, build_node!("firstName", :text => "Hans"))
19
+ assert_equal "Hans", doc.top['first_name']
20
+ end
21
+
22
+ def test_supply_custom_name
23
+ doc.push SomeModel.new
24
+ rule = Sawtooth::Rules::TextRule.new :first_name
25
+ rule.finish("root/didum/Text", doc, build_node!("Text", :text => "Hans"))
26
+ assert_equal "Hans", doc.top.first_name
27
+ end
28
+
29
+ def test_supply_conversion_block
30
+ doc.push Hash.new
31
+ rule = Sawtooth::Rules::TextRule.new(:value) { |str| str.strip.to_i }
32
+ rule.finish("root/didum/intValue", doc, build_node!("intValue", :text => " 1234\n"))
33
+ assert_equal 1234, doc.top[:value]
34
+ end
35
+
36
+ def test_supply_name_conversion_block
37
+ doc.push Hash.new
38
+ rule = Sawtooth::Rules::TextRule.new(Proc.new { |name| name.upcase.to_sym })
39
+ rule.finish("root/dadam/intValue", doc, build_node!("intValue", :text => " 1234\n"))
40
+ rule.finish("root/dadam/strValue", doc, build_node!("strValue", :text => " didum\n"))
41
+ assert_equal "1234", doc.top[:INTVALUE]
42
+ assert_equal "didum", doc.top[:STRVALUE]
43
+ end
44
+
45
+ def test_default_converter_converts_empty_line_to_nil
46
+ doc.push SomeModel.new
47
+ rule = Sawtooth::Rules::TextRule.new
48
+ rule.finish("root/firstName", doc, build_node!("firstName", :text => " \n"))
49
+ assert_nil doc.top.first_name
50
+ end
51
+
52
+ def test_appends_values_if_array
53
+ doc.push []
54
+ rule = Sawtooth::Rules::TextRule.new
55
+ rule.finish("root/firstName", doc, build_node!("firstName", :text => "Hans\n"))
56
+ rule.finish("root/lastName", doc, build_node!("lastName", :text => " Muster\n\n"))
57
+ assert_equal %w{Hans Muster}, doc.top
58
+ end
59
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ class Sawtooth::Rules::SetTest < MiniTest::Unit::TestCase
4
+ def setup
5
+ @set = Sawtooth::Rules::Set.new
6
+ @set.add "other/test/path", 10
7
+ @set.add "otherPath/test/*", 11
8
+ @set.add "other/**", 12
9
+ @set.add "other/path", 13
10
+
11
+ @set.add "didum/*", 20
12
+ @set.add "didum/user/*", 21
13
+
14
+ @set.add %r{\Asome/(magic|regex(/.*)?)\z}, 3
15
+
16
+ @set.add "some/path", 1
17
+ @set.add "some/path/here", 2
18
+ end
19
+
20
+ def test_adding_rules
21
+ assert_equal 2, @set.items.last.rule
22
+ end
23
+
24
+ def test_matching_static_rules
25
+ assert_equal 1, @set.find("some/path")
26
+ assert_equal 2, @set.find("some/path/here")
27
+ assert_equal 1, @set.find(%w{some path})
28
+ assert_equal 2, @set.find('some', 'path', 'here')
29
+ end
30
+
31
+ def test_matching_glob_rules
32
+ assert_equal 12, @set.find("other/didum")
33
+ assert_equal 12, @set.find("other/didum/dadam")
34
+ assert_equal 12, @set.find("other/path") # cannot be reached because of globbing
35
+ assert_equal 11, @set.find("otherPath/test/didum")
36
+ assert_nil @set.find("otherPath/test")
37
+
38
+ assert_equal 20, @set.find("didum/magic")
39
+ assert_equal 20, @set.find("didum/random")
40
+ assert_nil @set.find("didum/magic/boredom")
41
+ assert_nil @set.find("didum/magic/didum/darmdam")
42
+ end
43
+
44
+ def test_regex_paths
45
+ assert_equal 3, @set.find("some/magic")
46
+ assert_equal 3, @set.find("some/regex")
47
+ assert_equal 3, @set.find("some/regex/didum")
48
+ end
49
+ end
@@ -0,0 +1,25 @@
1
+ require 'minitest/autorun'
2
+
3
+ # load sawtooth
4
+ require 'sawtooth'
5
+
6
+ class MiniTest::Unit::TestCase
7
+
8
+ # Root directory, for tests
9
+ TEST_ROOT = File.dirname(__FILE__)
10
+
11
+ # Testing Stack
12
+ def doc; @doc ||= Sawtooth::Document.new end
13
+
14
+ # Helper which creates a new Sawtooth::Document::Node
15
+ # Instance.
16
+ #
17
+ def build_node!(name = "test", opts = {})
18
+ Sawtooth::Document::Node.new(opts[:ns] || opts[:namespace], name, opts[:attrs] || opts[:attributes] || {}, opts[:txt] || opts[:text] || '')
19
+ end
20
+
21
+ # Path to a file in test/files
22
+ def fixture_path(filename)
23
+ "#{TEST_ROOT}/files/#{filename}"
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sawtooth
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
+ platform: ruby
12
+ authors:
13
+ - Lukas Westermann
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-01-19 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ type: :runtime
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ prerelease: false
32
+ name: nokogiri
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ type: :development
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ hash: 63
42
+ segments:
43
+ - 0
44
+ - 9
45
+ - 2
46
+ version: 0.9.2
47
+ prerelease: false
48
+ name: rake
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ type: :development
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 15
58
+ segments:
59
+ - 0
60
+ - 4
61
+ - 0
62
+ version: 0.4.0
63
+ prerelease: false
64
+ name: appraisal
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ type: :development
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 39
74
+ segments:
75
+ - 2
76
+ - 10
77
+ - 0
78
+ version: 2.10.0
79
+ prerelease: false
80
+ name: minitest
81
+ version_requirements: *id004
82
+ description: Provides an interface on top of nokogiri to parse XML files like Apache Digester.
83
+ email:
84
+ - lukas.westermann@gmail.com
85
+ executables: []
86
+
87
+ extensions: []
88
+
89
+ extra_rdoc_files: []
90
+
91
+ files:
92
+ - .gitignore
93
+ - Gemfile
94
+ - README.md
95
+ - Rakefile
96
+ - lib/sawtooth.rb
97
+ - lib/sawtooth/builder.rb
98
+ - lib/sawtooth/document.rb
99
+ - lib/sawtooth/parser.rb
100
+ - lib/sawtooth/rules.rb
101
+ - lib/sawtooth/rules/base.rb
102
+ - lib/sawtooth/rules/call_rule.rb
103
+ - lib/sawtooth/rules/delegate_rule.rb
104
+ - lib/sawtooth/rules/set.rb
105
+ - lib/sawtooth/rules/text_rule.rb
106
+ - lib/sawtooth/version.rb
107
+ - sawtooth.gemspec
108
+ - test/files/delegate.xml
109
+ - test/files/statuses.xml
110
+ - test/sawtooth/builder_test.rb
111
+ - test/sawtooth/document_test.rb
112
+ - test/sawtooth/parser_test.rb
113
+ - test/sawtooth/readme_test.rb
114
+ - test/sawtooth/rules/delegate_rule_test.rb
115
+ - test/sawtooth/rules/text_rule_test.rb
116
+ - test/sawtooth/rules_set_test.rb
117
+ - test/test_helper.rb
118
+ homepage: ""
119
+ licenses: []
120
+
121
+ post_install_message:
122
+ rdoc_options: []
123
+
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ hash: 3
132
+ segments:
133
+ - 0
134
+ version: "0"
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ hash: 3
141
+ segments:
142
+ - 0
143
+ version: "0"
144
+ requirements: []
145
+
146
+ rubyforge_project: sawtooth
147
+ rubygems_version: 1.8.10
148
+ signing_key:
149
+ specification_version: 3
150
+ summary: Declarative XML parsing using nokogiri
151
+ test_files:
152
+ - test/files/delegate.xml
153
+ - test/files/statuses.xml
154
+ - test/sawtooth/builder_test.rb
155
+ - test/sawtooth/document_test.rb
156
+ - test/sawtooth/parser_test.rb
157
+ - test/sawtooth/readme_test.rb
158
+ - test/sawtooth/rules/delegate_rule_test.rb
159
+ - test/sawtooth/rules/text_rule_test.rb
160
+ - test/sawtooth/rules_set_test.rb
161
+ - test/test_helper.rb