sawtooth 0.2.0

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.
@@ -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