moxml 0.1.0 → 0.1.2
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.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +15 -0
- data/.github/workflows/release.yml +23 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +2 -0
- data/.rubocop_todo.yml +65 -0
- data/.ruby-version +1 -0
- data/Gemfile +10 -3
- data/README.adoc +401 -594
- data/lib/moxml/adapter/base.rb +102 -0
- data/lib/moxml/adapter/customized_oga/xml_declaration.rb +18 -0
- data/lib/moxml/adapter/customized_oga/xml_generator.rb +104 -0
- data/lib/moxml/adapter/nokogiri.rb +319 -0
- data/lib/moxml/adapter/oga.rb +318 -0
- data/lib/moxml/adapter/ox.rb +325 -0
- data/lib/moxml/adapter.rb +26 -170
- data/lib/moxml/attribute.rb +47 -14
- data/lib/moxml/builder.rb +64 -0
- data/lib/moxml/cdata.rb +4 -26
- data/lib/moxml/comment.rb +6 -22
- data/lib/moxml/config.rb +39 -15
- data/lib/moxml/context.rb +29 -0
- data/lib/moxml/declaration.rb +16 -26
- data/lib/moxml/doctype.rb +9 -0
- data/lib/moxml/document.rb +51 -63
- data/lib/moxml/document_builder.rb +87 -0
- data/lib/moxml/element.rb +63 -97
- data/lib/moxml/error.rb +20 -0
- data/lib/moxml/namespace.rb +12 -37
- data/lib/moxml/node.rb +78 -58
- data/lib/moxml/node_set.rb +19 -222
- data/lib/moxml/processing_instruction.rb +6 -25
- data/lib/moxml/text.rb +4 -26
- data/lib/moxml/version.rb +1 -1
- data/lib/moxml/xml_utils/encoder.rb +55 -0
- data/lib/moxml/xml_utils.rb +80 -0
- data/lib/moxml.rb +33 -33
- data/moxml.gemspec +1 -1
- data/spec/moxml/adapter/nokogiri_spec.rb +14 -0
- data/spec/moxml/adapter/oga_spec.rb +14 -0
- data/spec/moxml/adapter/ox_spec.rb +49 -0
- data/spec/moxml/all_with_adapters_spec.rb +46 -0
- data/spec/moxml/config_spec.rb +55 -0
- data/spec/moxml/error_spec.rb +71 -0
- data/spec/moxml/examples/adapter_spec.rb +27 -0
- data/spec/moxml_spec.rb +50 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/shared_examples/attribute.rb +165 -0
- data/spec/support/shared_examples/builder.rb +25 -0
- data/spec/support/shared_examples/cdata.rb +70 -0
- data/spec/support/shared_examples/comment.rb +65 -0
- data/spec/support/shared_examples/context.rb +35 -0
- data/spec/support/shared_examples/declaration.rb +93 -0
- data/spec/support/shared_examples/doctype.rb +25 -0
- data/spec/support/shared_examples/document.rb +110 -0
- data/spec/support/shared_examples/document_builder.rb +43 -0
- data/spec/support/shared_examples/edge_cases.rb +185 -0
- data/spec/support/shared_examples/element.rb +130 -0
- data/spec/support/shared_examples/examples/attribute.rb +42 -0
- data/spec/support/shared_examples/examples/basic_usage.rb +67 -0
- data/spec/support/shared_examples/examples/memory.rb +54 -0
- data/spec/support/shared_examples/examples/namespace.rb +65 -0
- data/spec/support/shared_examples/examples/readme_examples.rb +100 -0
- data/spec/support/shared_examples/examples/thread_safety.rb +43 -0
- data/spec/support/shared_examples/examples/xpath.rb +39 -0
- data/spec/support/shared_examples/integration.rb +135 -0
- data/spec/support/shared_examples/namespace.rb +96 -0
- data/spec/support/shared_examples/node.rb +110 -0
- data/spec/support/shared_examples/node_set.rb +90 -0
- data/spec/support/shared_examples/processing_instruction.rb +88 -0
- data/spec/support/shared_examples/text.rb +66 -0
- data/spec/support/shared_examples/xml_adapter.rb +191 -0
- data/spec/support/xml_matchers.rb +27 -0
- metadata +55 -6
- data/.github/workflows/main.yml +0 -27
- data/lib/moxml/error_handler.rb +0 -77
- data/lib/moxml/errors.rb +0 -169
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "xml_utils/encoder"
|
4
|
+
|
5
|
+
# Ruby 3.3+ requires the URI module to be explicitly required
|
6
|
+
require "uri" unless defined?(::URI)
|
7
|
+
|
8
|
+
module Moxml
|
9
|
+
module XmlUtils
|
10
|
+
def encode_entities(text, mode = nil)
|
11
|
+
Encoder.new(text, mode).call
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate_declaration_version(version)
|
15
|
+
return if ::Moxml::Declaration::ALLOWED_VERSIONS.include?(version)
|
16
|
+
|
17
|
+
raise ValidationError, "Invalid XML version: #{version}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_declaration_encoding(encoding)
|
21
|
+
return if encoding.nil?
|
22
|
+
|
23
|
+
begin
|
24
|
+
Encoding.find(encoding)
|
25
|
+
rescue ArgumentError
|
26
|
+
raise ValidationError, "Invalid encoding: #{encoding}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def validate_declaration_standalone(standalone)
|
31
|
+
return if standalone.nil?
|
32
|
+
return if ::Moxml::Declaration::ALLOWED_STANDALONE.include?(standalone)
|
33
|
+
|
34
|
+
raise ValidationError, "Invalid standalone value: #{standalone}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate_comment_content(text)
|
38
|
+
if text.start_with?("-") || text.end_with?("-")
|
39
|
+
raise ValidationError, "XML comment cannot start or end with a hyphen"
|
40
|
+
end
|
41
|
+
|
42
|
+
return unless text.include?("--")
|
43
|
+
|
44
|
+
raise ValidationError, "XML comment cannot contain double hyphens (--)"
|
45
|
+
end
|
46
|
+
|
47
|
+
def validate_element_name(name)
|
48
|
+
return if name.is_a?(String) && name.match?(/^[a-zA-Z_][\w\-.:]*$/)
|
49
|
+
|
50
|
+
raise ValidationError, "Invalid XML name: #{name}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def validate_pi_target(target)
|
54
|
+
return if target.is_a?(String) && target.match?(/^[a-zA-Z_][\w\-.]*$/)
|
55
|
+
|
56
|
+
raise ValidationError, "Invalid XML target: #{target}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def validate_uri(uri)
|
60
|
+
return if uri.empty? || uri.match?(/\A#{::URI::DEFAULT_PARSER.make_regexp}\z/)
|
61
|
+
|
62
|
+
raise ValidationError, "Invalid URI: #{uri}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def validate_prefix(prefix)
|
66
|
+
return if prefix.match?(/\A[a-zA-Z_][\w-]*\z/)
|
67
|
+
|
68
|
+
raise ValidationError, "Invalid namespace prefix: #{prefix}"
|
69
|
+
end
|
70
|
+
|
71
|
+
def normalize_xml_value(value)
|
72
|
+
case value
|
73
|
+
when nil then ""
|
74
|
+
when true then "true"
|
75
|
+
when false then "false"
|
76
|
+
else value.to_s
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/moxml.rb
CHANGED
@@ -1,44 +1,44 @@
|
|
1
|
-
#
|
2
|
-
require_relative "moxml/version"
|
3
|
-
require_relative "moxml/config"
|
4
|
-
require_relative "moxml/document"
|
5
|
-
require_relative "moxml/node"
|
6
|
-
require_relative "moxml/element"
|
7
|
-
require_relative "moxml/text"
|
8
|
-
require_relative "moxml/cdata_section"
|
9
|
-
require_relative "moxml/comment"
|
10
|
-
require_relative "moxml/processing_instruction"
|
11
|
-
require_relative "moxml/visitor"
|
12
|
-
require_relative "moxml/errors"
|
13
|
-
require_relative "moxml/backends/base"
|
1
|
+
# frozen_string_literal: true
|
14
2
|
|
15
3
|
module Moxml
|
16
4
|
class << self
|
17
|
-
def
|
18
|
-
|
5
|
+
def new(adapter = nil, &block)
|
6
|
+
context = Context.new(adapter)
|
7
|
+
context.config.instance_eval(&block) if block_given?
|
8
|
+
context
|
19
9
|
end
|
20
10
|
|
21
11
|
def configure
|
22
|
-
yield
|
12
|
+
yield Config.default if block_given?
|
23
13
|
end
|
24
14
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
15
|
+
def with_config(adapter_name = nil, strict_parsing = nil, default_encoding = nil)
|
16
|
+
original_config = Config.default.dup
|
17
|
+
|
18
|
+
configure do |config|
|
19
|
+
config.adapter = adapter_name unless adapter_name.nil?
|
20
|
+
config.strict_parsing = strict_parsing unless strict_parsing.nil?
|
21
|
+
config.default_encoding = default_encoding unless default_encoding.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
yield if block_given?
|
25
|
+
|
26
|
+
# restore the original config
|
27
|
+
configure do |config|
|
28
|
+
config.adapter = original_config.adapter_name
|
29
|
+
config.strict_parsing = original_config.strict_parsing
|
30
|
+
config.default_encoding = original_config.default_encoding
|
31
|
+
end
|
32
|
+
original_config = nil
|
42
33
|
end
|
43
34
|
end
|
44
35
|
end
|
36
|
+
|
37
|
+
require_relative "moxml/version"
|
38
|
+
require_relative "moxml/document"
|
39
|
+
require_relative "moxml/document_builder"
|
40
|
+
require_relative "moxml/error"
|
41
|
+
require_relative "moxml/builder"
|
42
|
+
require_relative "moxml/config"
|
43
|
+
require_relative "moxml/context"
|
44
|
+
require_relative "moxml/adapter"
|
data/moxml.gemspec
CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
# RubyGem that have been added into git.
|
26
26
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
27
27
|
`git ls-files -z`.split("\x0").reject do |f|
|
28
|
-
f.match(%r{^(test|
|
28
|
+
f.match(%r{^(test|features)/})
|
29
29
|
end
|
30
30
|
end
|
31
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "nokogiri"
|
4
|
+
require "moxml/adapter/nokogiri"
|
5
|
+
|
6
|
+
RSpec.describe Moxml::Adapter::Nokogiri do
|
7
|
+
around do |example|
|
8
|
+
Moxml.with_config(:nokogiri, true, "UTF-8") do
|
9
|
+
example.run
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it_behaves_like "xml adapter"
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "oga"
|
4
|
+
require "moxml/adapter/oga"
|
5
|
+
|
6
|
+
RSpec.describe Moxml::Adapter::Oga do
|
7
|
+
around do |example|
|
8
|
+
Moxml.with_config(:oga, true, "UTF-8") do
|
9
|
+
example.run
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it_behaves_like "xml adapter"
|
14
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ox"
|
4
|
+
require "moxml/adapter/ox"
|
5
|
+
|
6
|
+
RSpec.describe Moxml::Adapter::Ox, skip: "Ox will be added later" do
|
7
|
+
before(:all) do
|
8
|
+
Moxml.configure do |config|
|
9
|
+
config.adapter = :ox
|
10
|
+
config.strict_parsing = true
|
11
|
+
config.default_encoding = "UTF-8"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it_behaves_like "xml adapter"
|
16
|
+
|
17
|
+
describe "text handling" do
|
18
|
+
let(:doc) { described_class.create_document }
|
19
|
+
let(:element) { described_class.create_native_element("test") }
|
20
|
+
|
21
|
+
it "creates text nodes as strings" do
|
22
|
+
text = described_class.create_native_text("content")
|
23
|
+
expect(text).to be_a(String)
|
24
|
+
expect(text).to eq("content")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "adds text nodes to elements" do
|
28
|
+
text = described_class.create_native_text("content")
|
29
|
+
described_class.add_child(element, text)
|
30
|
+
expect(element.nodes.first).to eq("content")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "xpath support" do
|
35
|
+
let(:doc) { described_class.parse("<root><child id='1'>text</child></root>") }
|
36
|
+
|
37
|
+
it "supports basic element matching" do
|
38
|
+
nodes = described_class.xpath(doc, "//child")
|
39
|
+
expect(nodes.size).to eq(1)
|
40
|
+
expect(nodes.first.name).to eq("child")
|
41
|
+
end
|
42
|
+
|
43
|
+
it "supports attribute matching" do
|
44
|
+
nodes = described_class.xpath(doc, "//child[@id='1']")
|
45
|
+
expect(nodes.size).to eq(1)
|
46
|
+
expect(nodes.first.attributes["id"]).to eq("1")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe "Test all shared examples" do
|
4
|
+
all_shared_examples = [
|
5
|
+
"Moxml::Node",
|
6
|
+
"Moxml::Namespace",
|
7
|
+
"Moxml::Attribute",
|
8
|
+
"Moxml::NodeSet",
|
9
|
+
"Moxml::Element",
|
10
|
+
"Moxml::Cdata",
|
11
|
+
"Moxml::Comment",
|
12
|
+
"Moxml::Text",
|
13
|
+
"Moxml::ProcessingInstruction",
|
14
|
+
"Moxml::Declaration",
|
15
|
+
"Moxml::Doctype",
|
16
|
+
"Moxml::Document",
|
17
|
+
"Moxml::Context",
|
18
|
+
"Moxml::Builder",
|
19
|
+
"Moxml::DocumentBuilder",
|
20
|
+
"Moxml Integration",
|
21
|
+
"Moxml Edge Cases",
|
22
|
+
"Attribute Examples",
|
23
|
+
"Basic Usage Examples",
|
24
|
+
"Namespace Examples",
|
25
|
+
"README Examples",
|
26
|
+
"XPath Examples",
|
27
|
+
"Memory Usage Examples",
|
28
|
+
"Thread Safety Examples"
|
29
|
+
]
|
30
|
+
|
31
|
+
Moxml::Adapter::AVALIABLE_ADAPTERS.each do |adapter_name|
|
32
|
+
# [:nokogiri].each do |adapter_name|
|
33
|
+
# [:oga].each do |adapter_name|
|
34
|
+
context "with #{adapter_name}" do
|
35
|
+
around do |example|
|
36
|
+
Moxml.with_config(adapter_name) do
|
37
|
+
example.run
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
all_shared_examples.each do |shared_example_name|
|
42
|
+
it_behaves_like shared_example_name
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# spec/moxml/config_spec.rb
|
4
|
+
RSpec.describe Moxml::Config do
|
5
|
+
subject(:config) { described_class.new }
|
6
|
+
|
7
|
+
describe "#initialize" do
|
8
|
+
it "sets default values" do
|
9
|
+
expect(config.adapter_name).to eq(:nokogiri)
|
10
|
+
expect(config.strict_parsing).to be true
|
11
|
+
expect(config.default_encoding).to eq("UTF-8")
|
12
|
+
expect(config.default_indent).to eq(2)
|
13
|
+
expect(config.entity_encoding).to eq(:basic)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#adapter=" do
|
18
|
+
it "sets valid adapter" do
|
19
|
+
config.adapter = :ox
|
20
|
+
expect(config.adapter_name).to eq(:ox)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "raises error for invalid adapter" do
|
24
|
+
expect { config.adapter = :invalid }.to raise_error(ArgumentError)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "requires adapter gem" do
|
28
|
+
expect { config.adapter = :oga }.not_to raise_error
|
29
|
+
|
30
|
+
expect(defined?(::Oga)).to be_truthy
|
31
|
+
end
|
32
|
+
|
33
|
+
it "handles missing gems" do
|
34
|
+
allow(Moxml::Adapter).to receive(:require).and_raise(LoadError)
|
35
|
+
expect { config.adapter = :nokogiri }.to raise_error(LoadError)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#adapter" do
|
40
|
+
it "returns nokogiri adapter by default" do
|
41
|
+
expect(config.adapter).to eq(Moxml::Adapter::Nokogiri)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "caches adapter instance" do
|
45
|
+
adapter = config.adapter
|
46
|
+
expect(config.adapter.object_id).to eq(adapter.object_id)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "resets cached adapter when changing adapter type" do
|
50
|
+
original = config.adapter
|
51
|
+
config.adapter = :ox
|
52
|
+
expect(config.adapter).not_to eq(original)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# spec/moxml/errors_spec.rb
|
4
|
+
RSpec.describe "Moxml errors" do
|
5
|
+
describe Moxml::Error do
|
6
|
+
it "is a StandardError" do
|
7
|
+
expect(Moxml::Error.new).to be_a(StandardError)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Moxml::ParseError do
|
12
|
+
it "includes line and column information" do
|
13
|
+
error = Moxml::ParseError.new("Invalid XML", line: 5, column: 10)
|
14
|
+
expect(error.line).to eq(5)
|
15
|
+
expect(error.column).to eq(10)
|
16
|
+
expect(error.message).to eq("Invalid XML")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "works without line and column" do
|
20
|
+
error = Moxml::ParseError.new("Invalid XML")
|
21
|
+
expect(error.line).to be_nil
|
22
|
+
expect(error.column).to be_nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe Moxml::ValidationError do
|
27
|
+
it "handles validation errors" do
|
28
|
+
error = Moxml::ValidationError.new("Invalid document structure")
|
29
|
+
expect(error.message).to eq("Invalid document structure")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe Moxml::XPathError do
|
34
|
+
it "handles XPath errors" do
|
35
|
+
error = Moxml::XPathError.new("Invalid XPath expression")
|
36
|
+
expect(error.message).to eq("Invalid XPath expression")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe Moxml::NamespaceError do
|
41
|
+
it "handles namespace errors" do
|
42
|
+
error = Moxml::NamespaceError.new("Invalid namespace URI")
|
43
|
+
expect(error.message).to eq("Invalid namespace URI")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "error handling in context" do
|
48
|
+
let(:context) { Moxml.new }
|
49
|
+
|
50
|
+
it "raises ParseError for invalid XML" do
|
51
|
+
expect do
|
52
|
+
context.parse("<invalid>")
|
53
|
+
end.to raise_error(Moxml::ParseError)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "raises XPathError for invalid XPath" do
|
57
|
+
doc = context.parse("<root/>")
|
58
|
+
expect do
|
59
|
+
doc.xpath("///")
|
60
|
+
end.to raise_error(Moxml::XPathError)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "raises NamespaceError for invalid namespace" do
|
64
|
+
doc = context.parse("<root/>")
|
65
|
+
|
66
|
+
expect do
|
67
|
+
doc.root.add_namespace("xml", "http//invalid.com")
|
68
|
+
end.to raise_error(Moxml::NamespaceError, "Invalid URI: http//invalid.com")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe "Adapter Examples" do
|
4
|
+
let(:xml) { "<root><child>text</child></root>" }
|
5
|
+
|
6
|
+
describe "Serialization consistency" do
|
7
|
+
it "produces equivalent XML across adapters",
|
8
|
+
skip: "No easy way to exclude the declaration from Nokogiri documents" do
|
9
|
+
docs = Moxml::Adapter::AVALIABLE_ADAPTERS.map do |adapter|
|
10
|
+
Moxml.new(adapter).parse(xml, fragment: true)
|
11
|
+
end
|
12
|
+
|
13
|
+
xmls = docs.map { |doc| normalize_xml(doc.to_xml) }
|
14
|
+
expect(xmls.uniq.size).to eq(1)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def normalize_xml(xml)
|
20
|
+
xml.gsub(/>\s+</, "><")
|
21
|
+
.gsub(/\s+/, " ")
|
22
|
+
.gsub(/ >/, ">")
|
23
|
+
.gsub(/\?></, "?>\n<")
|
24
|
+
.strip
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/moxml_spec.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# spec/moxml_spec.rb
|
4
|
+
RSpec.describe Moxml do
|
5
|
+
it "has a version number" do
|
6
|
+
expect(Moxml::VERSION).not_to be_nil
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ".new" do
|
10
|
+
it "creates a new context" do
|
11
|
+
expect(Moxml.new).to be_a(Moxml::Context)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "accepts adapter specification" do
|
15
|
+
context = Moxml.new(:nokogiri)
|
16
|
+
expect(context.config.adapter_name).to eq(:nokogiri)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "raises error for invalid adapter" do
|
20
|
+
expect { Moxml.new(:invalid) }.to raise_error(ArgumentError)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ".configure" do
|
25
|
+
around do |example|
|
26
|
+
# preserve the original config because it may be changed in examples
|
27
|
+
Moxml.with_config { example.run }
|
28
|
+
end
|
29
|
+
|
30
|
+
it "sets default values without a block" do
|
31
|
+
Moxml.configure
|
32
|
+
|
33
|
+
context = Moxml.new
|
34
|
+
expect(context.config.adapter_name).to eq(:nokogiri)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "uses configured options from the block" do
|
38
|
+
Moxml.configure do |config|
|
39
|
+
config.adapter = :oga
|
40
|
+
config.strict_parsing = false
|
41
|
+
config.default_encoding = "US-ASCII"
|
42
|
+
end
|
43
|
+
|
44
|
+
context = Moxml.new
|
45
|
+
expect(context.config.adapter_name).to eq(:oga)
|
46
|
+
expect(context.config.strict_parsing).to eq(false)
|
47
|
+
expect(context.config.default_encoding).to eq("US-ASCII")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "moxml"
|
4
|
+
require "nokogiri"
|
5
|
+
require "byebug"
|
6
|
+
|
7
|
+
Dir[File.expand_path("support/**/*.rb", __dir__)].each { |f| require f }
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.expect_with :rspec do |expectations|
|
11
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
12
|
+
end
|
13
|
+
|
14
|
+
config.mock_with :rspec do |mocks|
|
15
|
+
mocks.verify_partial_doubles = true
|
16
|
+
end
|
17
|
+
|
18
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
19
|
+
config.filter_run_when_matching :focus
|
20
|
+
config.example_status_persistence_file_path = "spec/examples.txt"
|
21
|
+
config.disable_monkey_patching!
|
22
|
+
config.warnings = true
|
23
|
+
|
24
|
+
config.order = :random
|
25
|
+
Kernel.srand config.seed
|
26
|
+
end
|
27
|
+
|
28
|
+
Moxml.configure do |config|
|
29
|
+
config.adapter = :nokogiri
|
30
|
+
config.strict_parsing = true
|
31
|
+
config.default_encoding = "UTF-8"
|
32
|
+
end
|