ronin-web 0.3.0.rc1 → 1.0.0.beta2

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 (148) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +11 -0
  3. data/.github/workflows/ruby.yml +31 -0
  4. data/.gitignore +13 -0
  5. data/.mailmap +1 -0
  6. data/.ruby-version +1 -0
  7. data/COPYING.txt +3 -3
  8. data/ChangeLog.md +115 -70
  9. data/Gemfile +42 -37
  10. data/README.md +160 -145
  11. data/Rakefile +12 -3
  12. data/bin/ronin-web +9 -17
  13. data/data/new/nokogiri.rb.erb +12 -0
  14. data/data/new/server.rb.erb +22 -0
  15. data/data/new/spider.rb.erb +26 -0
  16. data/data/new/webapp/.gitignore +15 -0
  17. data/data/new/webapp/.ruby-version.erb +1 -0
  18. data/data/new/webapp/Dockerfile.erb +11 -0
  19. data/data/new/webapp/Gemfile +6 -0
  20. data/data/new/webapp/app.rb.erb +15 -0
  21. data/data/new/webapp/config.ru +4 -0
  22. data/data/new/webapp/docker-compose.yml.erb +9 -0
  23. data/gemspec.yml +38 -16
  24. data/lib/ronin/web/cli/command.rb +36 -0
  25. data/lib/ronin/web/cli/commands/diff.rb +106 -0
  26. data/lib/ronin/web/cli/commands/html.rb +174 -0
  27. data/lib/ronin/web/cli/commands/irb.rb +56 -0
  28. data/lib/ronin/web/cli/commands/new/nokogiri.rb +85 -0
  29. data/lib/ronin/web/cli/commands/new/server.rb +96 -0
  30. data/lib/ronin/web/cli/commands/new/spider.rb +315 -0
  31. data/lib/ronin/web/cli/commands/new/webapp.rb +123 -0
  32. data/lib/ronin/web/cli/commands/new.rb +64 -0
  33. data/lib/ronin/web/cli/commands/reverse_proxy.rb +215 -0
  34. data/lib/ronin/web/cli/commands/server.rb +155 -0
  35. data/lib/ronin/web/cli/commands/spider.rb +822 -0
  36. data/lib/ronin/web/cli/ruby_shell.rb +50 -0
  37. data/lib/ronin/web/cli.rb +49 -0
  38. data/lib/ronin/web/html.rb +85 -0
  39. data/lib/ronin/web/mechanize.rb +34 -36
  40. data/lib/ronin/web/root.rb +27 -0
  41. data/lib/ronin/web/version.rb +7 -10
  42. data/lib/ronin/web/xml.rb +85 -0
  43. data/lib/ronin/web.rb +372 -13
  44. data/man/ronin-web-diff.1 +41 -0
  45. data/man/ronin-web-diff.1.md +30 -0
  46. data/man/ronin-web-html.1 +89 -0
  47. data/man/ronin-web-html.1.md +66 -0
  48. data/man/ronin-web-irb.1 +31 -0
  49. data/man/ronin-web-irb.1.md +22 -0
  50. data/man/ronin-web-new-nokogiri.1 +41 -0
  51. data/man/ronin-web-new-nokogiri.1.md +30 -0
  52. data/man/ronin-web-new-server.1 +45 -0
  53. data/man/ronin-web-new-server.1.md +33 -0
  54. data/man/ronin-web-new-spider.1 +173 -0
  55. data/man/ronin-web-new-spider.1.md +129 -0
  56. data/man/ronin-web-new-webapp.1 +53 -0
  57. data/man/ronin-web-new-webapp.1.md +39 -0
  58. data/man/ronin-web-new.1 +59 -0
  59. data/man/ronin-web-new.1.md +44 -0
  60. data/man/ronin-web-reverse-proxy.1 +63 -0
  61. data/man/ronin-web-reverse-proxy.1.md +47 -0
  62. data/man/ronin-web-server.1 +59 -0
  63. data/man/ronin-web-server.1.md +43 -0
  64. data/man/ronin-web-spider.1 +225 -0
  65. data/man/ronin-web-spider.1.md +168 -0
  66. data/man/ronin-web.1 +41 -0
  67. data/man/ronin-web.1.md +30 -0
  68. data/ronin-web.gemspec +39 -109
  69. data/spec/cli/ruby_shell_spec.rb +14 -0
  70. data/spec/html_spec.rb +43 -0
  71. data/spec/mechanize_spec.rb +72 -0
  72. data/spec/spec_helper.rb +5 -3
  73. data/spec/web_spec.rb +97 -0
  74. data/spec/xml_spec.rb +42 -0
  75. metadata +236 -224
  76. data/.gemtest +0 -0
  77. data/data/ronin/web/user_agents.yml +0 -247
  78. data/lib/ronin/network/mixins/web.rb +0 -258
  79. data/lib/ronin/web/config.rb +0 -34
  80. data/lib/ronin/web/extensions/nokogiri/xml/attr.rb +0 -47
  81. data/lib/ronin/web/extensions/nokogiri/xml/document.rb +0 -48
  82. data/lib/ronin/web/extensions/nokogiri/xml/element.rb +0 -57
  83. data/lib/ronin/web/extensions/nokogiri/xml/node.rb +0 -86
  84. data/lib/ronin/web/extensions/nokogiri/xml/text.rb +0 -47
  85. data/lib/ronin/web/extensions/nokogiri/xml.rb +0 -27
  86. data/lib/ronin/web/extensions/nokogiri.rb +0 -23
  87. data/lib/ronin/web/extensions.rb +0 -23
  88. data/lib/ronin/web/middleware/base.rb +0 -144
  89. data/lib/ronin/web/middleware/directories.rb +0 -179
  90. data/lib/ronin/web/middleware/files.rb +0 -144
  91. data/lib/ronin/web/middleware/filters/campaign_filter.rb +0 -77
  92. data/lib/ronin/web/middleware/filters/ip_filter.rb +0 -73
  93. data/lib/ronin/web/middleware/filters/path_filter.rb +0 -73
  94. data/lib/ronin/web/middleware/filters/referer_filter.rb +0 -71
  95. data/lib/ronin/web/middleware/filters/user_agent_filter.rb +0 -71
  96. data/lib/ronin/web/middleware/filters/vhost_filter.rb +0 -71
  97. data/lib/ronin/web/middleware/filters.rb +0 -28
  98. data/lib/ronin/web/middleware/helpers.rb +0 -145
  99. data/lib/ronin/web/middleware/proxy.rb +0 -265
  100. data/lib/ronin/web/middleware/proxy_request.rb +0 -262
  101. data/lib/ronin/web/middleware/request.rb +0 -79
  102. data/lib/ronin/web/middleware/response.rb +0 -33
  103. data/lib/ronin/web/middleware/router.rb +0 -167
  104. data/lib/ronin/web/middleware/rule.rb +0 -103
  105. data/lib/ronin/web/middleware.rb +0 -27
  106. data/lib/ronin/web/proxy/app.rb +0 -32
  107. data/lib/ronin/web/proxy/base.rb +0 -46
  108. data/lib/ronin/web/proxy/web.rb +0 -46
  109. data/lib/ronin/web/proxy.rb +0 -25
  110. data/lib/ronin/web/server/app.rb +0 -32
  111. data/lib/ronin/web/server/base.rb +0 -461
  112. data/lib/ronin/web/server/web.rb +0 -66
  113. data/lib/ronin/web/server.rb +0 -25
  114. data/lib/ronin/web/spider.rb +0 -120
  115. data/lib/ronin/web/user_agents.rb +0 -196
  116. data/lib/ronin/web/web.rb +0 -560
  117. data/spec/helpers/output.rb +0 -3
  118. data/spec/web/extensions/nokogiri_spec.rb +0 -38
  119. data/spec/web/helpers/rack_app.rb +0 -24
  120. data/spec/web/helpers/root/test1/index.html +0 -1
  121. data/spec/web/helpers/root/test1/test1.txt +0 -1
  122. data/spec/web/helpers/root/test1.txt +0 -1
  123. data/spec/web/helpers/root/test2/test2.txt +0 -1
  124. data/spec/web/helpers/root/test2.txt +0 -1
  125. data/spec/web/helpers/root/test3/test3.txt +0 -1
  126. data/spec/web/helpers/root/test3.txt +0 -1
  127. data/spec/web/helpers/root.rb +0 -15
  128. data/spec/web/mechanize_spec.rb +0 -62
  129. data/spec/web/middleware/directories_spec.rb +0 -86
  130. data/spec/web/middleware/files_spec.rb +0 -57
  131. data/spec/web/middleware/filters/campaign_filter_spec.rb +0 -30
  132. data/spec/web/middleware/filters/ip_filter_spec.rb +0 -25
  133. data/spec/web/middleware/filters/path_filter_spec.rb +0 -29
  134. data/spec/web/middleware/filters/referer_filter_spec.rb +0 -25
  135. data/spec/web/middleware/filters/user_agent_filter_spec.rb +0 -25
  136. data/spec/web/middleware/filters/vhost_filter_spec.rb +0 -23
  137. data/spec/web/middleware/proxy_spec.rb +0 -67
  138. data/spec/web/middleware/response_spec.rb +0 -20
  139. data/spec/web/middleware/router_spec.rb +0 -65
  140. data/spec/web/middleware/rule_spec.rb +0 -37
  141. data/spec/web/proxy/base_spec.rb +0 -8
  142. data/spec/web/server/base_spec.rb +0 -77
  143. data/spec/web/server/classes/public1/static1.txt +0 -1
  144. data/spec/web/server/classes/public2/static2.txt +0 -1
  145. data/spec/web/server/classes/sub_app.rb +0 -13
  146. data/spec/web/server/classes/test_app.rb +0 -20
  147. data/spec/web/user_agents_spec.rb +0 -56
  148. data/spec/web/web_spec.rb +0 -101
data/ronin-web.gemspec CHANGED
@@ -2,130 +2,60 @@
2
2
 
3
3
  require 'yaml'
4
4
 
5
- Gem::Specification.new do |gemspec|
6
- root = File.dirname(__FILE__)
7
- lib_dir = File.join(root,'lib')
8
- files = if File.directory?('.git')
9
- `git ls-files`.split($/)
10
- elsif File.directory?('.hg')
11
- `hg manifest`.split($/)
12
- elsif File.directory?('.svn')
13
- `svn ls -R`.split($/).select { |path| File.file?(path) }
14
- else
15
- Dir['{**/}{.*,*}'].select { |path| File.file?(path) }
16
- end
5
+ Gem::Specification.new do |gem|
6
+ gemspec = YAML.load_file('gemspec.yml')
17
7
 
18
- filter_files = lambda { |paths|
19
- case paths
20
- when Array
21
- (files & paths)
22
- when String
23
- (files & Dir[paths])
24
- end
25
- }
26
-
27
- version = {
28
- :file => 'ronin/web/version',
29
- :constant => 'Ronin::Web::VERSION'
30
- }
31
-
32
- defaults = {
33
- 'name' => File.basename(root),
34
- 'files' => files,
35
- 'executables' => filter_files['bin/*'].map { |path| File.basename(path) },
36
- 'test_files' => filter_files['{test/{**/}*_test.rb,spec/{**/}*_spec.rb}'],
37
- 'extra_doc_files' => filter_files['*.{txt,rdoc,md,markdown,tt,textile}'],
38
- }
8
+ gem.name = gemspec.fetch('name')
9
+ gem.version = gemspec.fetch('version') do
10
+ lib_dir = File.join(File.dirname(__FILE__),'lib')
11
+ $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
39
12
 
40
- metadata = defaults.merge(YAML.load_file('gemspec.yml'))
13
+ require 'ronin/web/version'
14
+ Ronin::Web::VERSION
15
+ end
41
16
 
42
- gemspec.name = metadata.fetch('name',defaults[:name])
43
- gemspec.version = if metadata['version']
44
- metadata['version']
45
- else
46
- $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
17
+ gem.summary = gemspec['summary']
18
+ gem.description = gemspec['description']
19
+ gem.licenses = Array(gemspec['license'])
20
+ gem.authors = Array(gemspec['authors'])
21
+ gem.email = gemspec['email']
22
+ gem.homepage = gemspec['homepage']
47
23
 
48
- require version[:file]
49
- eval(version[:constant])
50
- end
24
+ glob = lambda { |patterns| gem.files & Dir[*patterns] }
51
25
 
52
- gemspec.summary = metadata.fetch('summary',metadata['description'])
53
- gemspec.description = metadata.fetch('description',metadata['summary'])
26
+ gem.files = `git ls-files`.split($/)
27
+ gem.files = glob[gemspec['files']] if gemspec['files']
28
+ gem.files += Array(gemspec['generated_files'])
54
29
 
55
- case metadata['license']
56
- when Array
57
- gemspec.licenses = metadata['license']
58
- when String
59
- gemspec.license = metadata['license']
30
+ gem.executables = gemspec.fetch('executables') do
31
+ glob['bin/*'].map { |path| File.basename(path) }
60
32
  end
33
+ gem.default_executable = gem.executables.first if Gem::VERSION < '1.7.'
61
34
 
62
- case metadata['authors']
63
- when Array
64
- gemspec.authors = metadata['authors']
65
- when String
66
- gemspec.author = metadata['authors']
67
- end
68
-
69
- gemspec.email = metadata['email']
70
- gemspec.homepage = metadata['homepage']
35
+ gem.extensions = glob[gemspec['extensions'] || 'ext/**/extconf.rb']
36
+ gem.test_files = glob[gemspec['test_files'] || 'spec/{**/}*_spec.rb']
37
+ gem.extra_rdoc_files = glob[gemspec['extra_doc_files'] || '*.{txt,md}']
71
38
 
72
- case metadata['require_paths']
73
- when Array
74
- gemspec.require_paths = metadata['require_paths']
75
- when String
76
- gemspec.require_path = metadata['require_paths']
77
- end
39
+ gem.require_paths = Array(gemspec.fetch('require_paths') {
40
+ %w[ext lib].select { |dir| File.directory?(dir) }
41
+ })
78
42
 
79
- gemspec.files = filter_files[metadata['files']]
43
+ gem.requirements = gemspec['requirements']
44
+ gem.required_ruby_version = gemspec['required_ruby_version']
45
+ gem.required_rubygems_version = gemspec['required_rubygems_version']
46
+ gem.post_install_message = gemspec['post_install_message']
80
47
 
81
- gemspec.executables = metadata['executables']
82
- gemspec.extensions = metadata['extensions']
83
-
84
- if Gem::VERSION < '1.7.'
85
- gemspec.default_executable = gemspec.executables.first
86
- end
87
-
88
- gemspec.test_files = filter_files[metadata['test_files']]
89
-
90
- unless gemspec.files.include?('.document')
91
- gemspec.extra_rdoc_files = metadata['extra_doc_files']
92
- end
93
-
94
- gemspec.post_install_message = metadata['post_install_message']
95
- gemspec.requirements = metadata['requirements']
96
-
97
- if gemspec.respond_to?(:required_ruby_version=)
98
- gemspec.required_ruby_version = metadata['required_ruby_version']
99
- end
100
-
101
- if gemspec.respond_to?(:required_rubygems_version=)
102
- gemspec.required_rubygems_version = metadata['required_ruby_version']
103
- end
104
-
105
- parse_versions = lambda { |versions|
106
- case versions
107
- when Array
108
- versions.map { |v| v.to_s }
109
- when String
110
- versions.split(/,\s*/)
111
- end
112
- }
113
-
114
- if metadata['dependencies']
115
- metadata['dependencies'].each do |name,versions|
116
- gemspec.add_dependency(name,parse_versions[versions])
117
- end
118
- end
48
+ split = lambda { |string| string.split(/,\s*/) }
119
49
 
120
- if metadata['runtime_dependencies']
121
- metadata['runtime_dependencies'].each do |name,versions|
122
- gemspec.add_runtime_dependency(name,parse_versions[versions])
50
+ if gemspec['dependencies']
51
+ gemspec['dependencies'].each do |name,versions|
52
+ gem.add_dependency(name,split[versions])
123
53
  end
124
54
  end
125
55
 
126
- if metadata['development_dependencies']
127
- metadata['development_dependencies'].each do |name,versions|
128
- gemspec.add_development_dependency(name,parse_versions[versions])
56
+ if gemspec['development_dependencies']
57
+ gemspec['development_dependencies'].each do |name,versions|
58
+ gem.add_development_dependency(name,split[versions])
129
59
  end
130
60
  end
131
61
  end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ require 'ronin/web/cli/ruby_shell'
3
+
4
+ describe Ronin::Web::CLI::RubyShell do
5
+ describe "#initialize" do
6
+ it "must default #name to 'ronin-web'" do
7
+ expect(subject.name).to eq('ronin-web')
8
+ end
9
+
10
+ it "must default #context to Ronin::Web" do
11
+ expect(subject.context).to be(Ronin::Web)
12
+ end
13
+ end
14
+ end
data/spec/html_spec.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ require 'ronin/web/html'
3
+
4
+ describe Ronin::Web::HTML do
5
+ describe ".parse" do
6
+ let(:html) do
7
+ <<~HTML
8
+ <html>
9
+ <body>Hello</body>
10
+ </html>
11
+ HTML
12
+ end
13
+
14
+ it "must parse an HTML String and return a Nokogiri::HTML::Document" do
15
+ doc = subject.parse(html)
16
+
17
+ expect(doc).to be_kind_of(Nokogiri::HTML::Document)
18
+ expect(doc.at('body').inner_text).to eq("Hello")
19
+ end
20
+
21
+ context "when given a block" do
22
+ it "must yield the Nokogiri::HTML::Document object" do
23
+ expect { |b|
24
+ subject.parse(html,&b)
25
+ }.to yield_with_args(Nokogiri::HTML::Document)
26
+ end
27
+ end
28
+ end
29
+
30
+ describe ".build" do
31
+ it "must build an HTML document" do
32
+ doc = subject.build do
33
+ html {
34
+ body {
35
+ div { text("hello") }
36
+ }
37
+ }
38
+ end
39
+
40
+ expect(doc.to_html).to include("<html><body><div>hello</div></body></html>")
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+ require 'ronin/web/mechanize'
3
+
4
+ describe Ronin::Web::Mechanize do
5
+ describe "#initialize" do
6
+ context "when Ronin::Support::Network::HTTP.user_agent is set" do
7
+ let(:user_agent) { 'test' }
8
+
9
+ before { Ronin::Support::Network::HTTP.user_agent = user_agent }
10
+
11
+ it "should set #user_agent to Ronin::Support::Network::HTTP.user_agent" do
12
+ expect(subject.user_agent).to eq(user_agent)
13
+ end
14
+
15
+ after { Ronin::Support::Network::HTTP.user_agent = nil }
16
+ end
17
+
18
+ context "when the :user_agent option is given" do
19
+ context "and it's a String" do
20
+ let(:user_agent) { 'test2' }
21
+
22
+ subject { described_class.new(user_agent: user_agent) }
23
+
24
+ it "should set #user_agent to the custom User-Agent string" do
25
+ expect(subject.user_agent).to eq(user_agent)
26
+ end
27
+ end
28
+
29
+ context "and it's a Symbol" do
30
+ let(:user_agent) { :chrome_linux }
31
+ let(:expected_user_agent) do
32
+ Ronin::Support::Network::HTTP::UserAgents[user_agent]
33
+ end
34
+
35
+ subject { described_class.new(user_agent: user_agent) }
36
+
37
+ it "should set #user_agent to the custom User-Agent alias" do
38
+ expect(subject.user_agent).to eq(expected_user_agent)
39
+ end
40
+ end
41
+ end
42
+
43
+ let(:host) { '127.0.0.1' }
44
+ let(:port) { 8080 }
45
+ let(:proxy) { URI::HTTP.build(host: host, port: port) }
46
+
47
+ context "when Ronin::Support::Network::HTTP.proxy is set" do
48
+ before { Ronin::Support::Network::HTTP.proxy = proxy }
49
+
50
+ it "should set #proxy_addr and #proxy_port to Ronin::Support::Network::HTTP.proxy" do
51
+ expect(subject.proxy_addr).to eq(
52
+ Ronin::Support::Network::HTTP.proxy.host
53
+ )
54
+
55
+ expect(subject.proxy_port).to eq(
56
+ Ronin::Support::Network::HTTP.proxy.port
57
+ )
58
+ end
59
+
60
+ after { Ronin::Support::Network::HTTP.proxy = nil }
61
+ end
62
+
63
+ context "when the :proxy option is given" do
64
+ subject { described_class.new(proxy: proxy) }
65
+
66
+ it "should set #proxy_addr and #proxy_port to the custom proxy" do
67
+ expect(subject.proxy_addr).to eq(host)
68
+ expect(subject.proxy_port).to eq(port)
69
+ end
70
+ end
71
+ end
72
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'rspec'
2
- require 'ronin/spec/database'
2
+ require 'simplecov'
3
3
 
4
- require 'ronin/web/version'
4
+ SimpleCov.start
5
5
 
6
- include Ronin
6
+ RSpec.configure do |specs|
7
+ specs.filter_run_excluding :network
8
+ end
data/spec/web_spec.rb ADDED
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+ require 'ronin/web'
3
+
4
+ describe Ronin::Web do
5
+ let(:url) { 'https://example.com/' }
6
+
7
+ it "should have a VERSION constant" do
8
+ expect(subject.const_defined?('VERSION')).to eq(true)
9
+ end
10
+
11
+ describe ".html" do
12
+ it "should be able to parse HTML" do
13
+ doc = subject.html(%{
14
+ <html>
15
+ <body>Hello</body>
16
+ </html>
17
+ })
18
+
19
+ expect(doc.at('body').inner_text).to eq("Hello")
20
+ end
21
+ end
22
+
23
+ describe ".build_html" do
24
+ it "should be able to build HTML documents" do
25
+ doc = subject.build_html do
26
+ html {
27
+ body {
28
+ div { text("hello") }
29
+ }
30
+ }
31
+ end
32
+
33
+ expect(doc.to_html).to include("<html><body><div>hello</div></body></html>")
34
+ end
35
+ end
36
+
37
+ describe ".xml" do
38
+ it "should be able to parse XML" do
39
+ doc = subject.xml(%{
40
+ <?xml version="1.0"?>
41
+ <root>
42
+ <stuff>Hello</stuff>
43
+ </root>
44
+ })
45
+
46
+ expect(doc.at('stuff').inner_text).to eq("Hello")
47
+ end
48
+ end
49
+
50
+ describe ".build_xml" do
51
+ it "should be able to build XML documents" do
52
+ doc = subject.build_xml do
53
+ root {
54
+ stuff(name: 'bla') { text("hello") }
55
+ }
56
+ end
57
+
58
+ expect(doc.to_xml).to include("<root>\n <stuff name=\"bla\">hello</stuff>\n</root>")
59
+ end
60
+ end
61
+
62
+ describe ".open", :network do
63
+ it "must open URLs as temporary files" do
64
+ file = subject.open(url)
65
+
66
+ expect(file).to be_kind_of(StringIO)
67
+ expect(file.read).to include("Example Domain")
68
+ end
69
+ end
70
+
71
+ describe ".agent" do
72
+ it "must return a #{described_class}::Mechanize object" do
73
+ expect(subject.agent).to be_kind_of(described_class::Mechanize)
74
+ end
75
+
76
+ it "must return the same object each time" do
77
+ expect(subject.agent).to be(subject.agent)
78
+ end
79
+ end
80
+
81
+ describe ".get", :network do
82
+ it "should be able to get Mechanize pages" do
83
+ page = subject.get(url)
84
+
85
+ expect(page.class).to eq(Mechanize::Page)
86
+ expect(page.uri).to eq(URI(url))
87
+ end
88
+ end
89
+
90
+ describe ".get_body", :network do
91
+ it "should be able to get the bodies of Mechanize pages" do
92
+ body = subject.get_body(url)
93
+
94
+ expect(body).to include("Example Domain")
95
+ end
96
+ end
97
+ end
data/spec/xml_spec.rb ADDED
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'ronin/web/xml'
3
+
4
+ describe Ronin::Web::XML do
5
+ describe ".parse" do
6
+ let(:xml) do
7
+ <<~XML
8
+ <?xml version="1.0"?>
9
+ <root>
10
+ <stuff>Hello</stuff>
11
+ </root>
12
+ XML
13
+ end
14
+
15
+ it "must parse an XML String and return a Nokogiri::XML::Document" do
16
+ doc = subject.parse(xml)
17
+
18
+ expect(doc).to be_kind_of(Nokogiri::XML::Document)
19
+ expect(doc.at('stuff').inner_text).to eq("Hello")
20
+ end
21
+
22
+ context "when given a block" do
23
+ it "must yield the Nokogiri::XML::Document object" do
24
+ expect { |b|
25
+ subject.parse(xml,&b)
26
+ }.to yield_with_args(Nokogiri::XML::Document)
27
+ end
28
+ end
29
+ end
30
+
31
+ describe ".build" do
32
+ it "must build an XML document" do
33
+ doc = subject.build do
34
+ root {
35
+ stuff(name: 'bla') { text("hello") }
36
+ }
37
+ end
38
+
39
+ expect(doc.to_xml).to include("<root>\n <stuff name=\"bla\">hello</stuff>\n</root>")
40
+ end
41
+ end
42
+ end