require 'spec_helper'
require 'ronin/exploits/mixins/html'
require 'ronin/exploits/exploit'
describe Ronin::Exploits::Mixins::HTML do
module TestHTMLMixin
class TestExploit < Ronin::Exploits::Exploit
include Ronin::Exploits::Mixins::HTML
end
end
let(:test_exploit) { TestHTMLMixin::TestExploit }
subject { test_exploit.new }
describe "#attr_name" do
let(:name) { 'foo' }
it "must return the name as is" do
expect(subject.attr_name(name)).to eq(name)
end
context "when given a Symbol" do
let(:name) { :foo }
it "must return the String version of the Symbol" do
expect(subject.attr_name(name)).to eq(name.to_s)
end
end
context "when given `name_case: :lower`" do
let(:name) { 'FOO' }
it "must convert the name to lower-case" do
expect(subject.attr_name(name, name_case: :lower)).to eq(name.downcase)
end
end
context "when given `name_case: :upper`" do
it "must convert the name to upper-case" do
expect(subject.attr_name(name, name_case: :upper)).to eq(name.upcase)
end
end
context "when given `name_case: :random`" do
it "must randomize the case of the name" do
expect(subject.attr_name(name, name_case: :random)).to match(
/\A(?:Foo|fOo|foO|FOo|FoO|fOO|FOO)\z/
)
end
end
end
describe "#attr" do
let(:name) { 'foo' }
let(:value) { 'bar' }
it "must return name=\"value\"" do
expect(subject.attr(name,value)).to eq("#{name}=\"#{value}\"")
end
context "when given a Symbol for the name" do
let(:name) { :foo }
it "must accept a Symbol for the name" do
expect(subject.attr(name,value)).to eq("#{name}=\"#{value}\"")
end
end
context "when given a non-String for the value" do
let(:value) { 42 }
it "must accept a non-String for the value" do
expect(subject.attr(name,value)).to eq("#{name}=\"#{value}\"")
end
end
context "when given `name_case: :lower`" do
let(:name) { 'FOO' }
it "must convert the name to lower-case" do
expect(subject.attr(name,value, name_case: :lower)).to eq(
"#{name.downcase}=\"#{value}\""
)
end
end
context "when given `name_case: :upper`" do
it "must convert the name to upper-case" do
expect(subject.attr(name,value, name_case: :upper)).to eq(
"#{name.upcase}=\"#{value}\""
)
end
end
context "when given `name_case: :random`" do
it "must randomize the case of the name" do
expect(subject.attr(name,value, name_case: :random)).to match(
/\A(?:Foo|fOo|foO|FOo|FoO|fOO|FOO)=\"#{value}\"\z/
)
end
end
context "when given `quote: double`" do
it "must quote the value with double quotes" do
expect(subject.attr(name,value, quote: :double)).to eq(
"#{name}=\"#{value}\""
)
end
context "and when the value contains a double quote" do
let(:value) { "bar\"baz" }
it "must replace any double quotes with "" do
expect(subject.attr(name,value)).to eq("#{name}=\"bar"baz\"")
end
end
end
context "when given `quote: single`" do
it "must quote the value with single quotes" do
expect(subject.attr(name,value, quote: :single)).to eq(
"#{name}='#{value}'"
)
end
context "and when the value contains a single quote" do
let(:value) { "bar'baz" }
it "must replace any double quotes with ';" do
expect(subject.attr(name,value, quote: :single)).to eq(
"#{name}='bar'baz'"
)
end
end
end
context "when given `quote: backtick`" do
it "must quote the value with backticks" do
expect(subject.attr(name,value, quote: :backtick)).to eq(
"#{name}=`#{value}`"
)
end
end
context "when given `quote: nil`" do
it "must not quote the value" do
expect(subject.attr(name,value, quote: nil)).to eq(
"#{name}=#{value}"
)
end
context "and when the value contains a space" do
let(:value) { "bar baz" }
it "must replace any spaces with nbsp;;" do
expect(subject.attr(name,value, quote: nil)).to eq(
"#{name}=bar baz"
)
end
end
end
end
describe "#attr_list" do
let(:name1) { 'foo' }
let(:value1) { 'bar' }
let(:name2) { 'baz' }
let(:value2) { 'qux' }
let(:attrs) { {name1 => value1, name2 => value2} }
it "must return name=\"value\" ..." do
expect(subject.attr_list(attrs)).to eq(
"#{name1}=\"#{value1}\" #{name2}=\"#{value2}\""
)
end
context "when the attributes have Symbol names" do
let(:name1) { :foo }
let(:name2) { :baz }
it "must accept Symbols for attribute names" do
expect(subject.attr_list(attrs)).to eq(
"#{name1}=\"#{value1}\" #{name2}=\"#{value2}\""
)
end
end
context "when the attributes contains non-String values" do
let(:value1) { 42 }
let(:value2) { :qux }
it "must accept non-Strings for attribute values" do
expect(subject.attr_list(attrs)).to eq(
"#{name1}=\"#{value1}\" #{name2}=\"#{value2}\""
)
end
end
context "when given `name_case: :lower`" do
let(:name1) { 'FOO' }
let(:name2) { 'BAZ' }
it "must convert the attribute names to lower-case" do
expect(subject.attr_list(attrs, name_case: :lower)).to eq(
"#{name1.downcase}=\"#{value1}\" #{name2.downcase}=\"#{value2}\""
)
end
end
context "when given `name_case: :upper`" do
it "must convert the attribute names to upper-case" do
expect(subject.attr_list(attrs, name_case: :upper)).to eq(
"#{name1.upcase}=\"#{value1}\" #{name2.upcase}=\"#{value2}\""
)
end
end
context "when given `name_case: :random`" do
it "must randomize the case of each attribute name" do
expect(subject.attr_list(attrs, name_case: :random)).to match(
/\A(?:Foo|fOo|foO|FOo|FoO|fOO|FOO)=\"#{value1}\" (?:Baz|bAz|baZ|BAz|BaZ|bAZ|BAZ)=\"#{value2}\"\z/
)
end
end
context "when given `quote: double`" do
it "must quote the attribute values with double quotes" do
expect(subject.attr_list(attrs, quote: :double)).to eq(
"#{name1}=\"#{value1}\" #{name2}=\"#{value2}\""
)
end
context "and when an attribute value contains a double quote" do
let(:value1) { "bar\"baz" }
it "must replace any double quotes with "" do
expect(subject.attr_list(attrs)).to eq(
"#{name1}=\"bar"baz\" #{name2}=\"#{value2}\""
)
end
end
end
context "when given `quote: single`" do
it "must quote the attribute values with single quotes" do
expect(subject.attr_list(attrs, quote: :single)).to eq(
"#{name1}='#{value1}' #{name2}='#{value2}'"
)
end
context "and when an attribute value contains a single quote" do
let(:value1) { "bar'baz" }
it "must replace any double quotes with ';" do
expect(subject.attr_list(attrs, quote: :single)).to eq(
"#{name1}='bar'baz' #{name2}='#{value2}'"
)
end
end
end
context "when given `quote: backtick`" do
it "must quote the attribute values with backticks" do
expect(subject.attr_list(attrs, quote: :backtick)).to eq(
"#{name1}=`#{value1}` #{name2}=`#{value2}`"
)
end
end
context "when given `quote: nil`" do
it "must not quote the attribute values" do
expect(subject.attr_list(attrs, quote: nil)).to eq(
"#{name1}=#{value1} #{name2}=#{value2}"
)
end
context "and when the value contains a space" do
let(:value1) { "bar baz" }
it "must replace any spaces with nbsp;;" do
expect(subject.attr_list(attrs, quote: nil)).to eq(
"#{name1}=bar baz #{name2}=#{value2}"
)
end
end
end
end
describe "#tag_name" do
let(:name) { 'foo' }
it "must return the name as is" do
expect(subject.tag_name(name)).to eq(name)
end
context "when given a Symbol" do
let(:name) { :foo }
it "must return the String version of the Symbol" do
expect(subject.tag_name(name)).to eq(name.to_s)
end
end
context "when given `name_case: :lower`" do
let(:name) { 'FOO' }
it "must convert the name to lower-case" do
expect(subject.tag_name(name, name_case: :lower)).to eq(name.downcase)
end
end
context "when given `name_case: :upper`" do
it "must convert the name to upper-case" do
expect(subject.tag_name(name, name_case: :upper)).to eq(name.upcase)
end
end
context "when given `name_case: :random`" do
it "must randomize the case of the name" do
expect(subject.tag_name(name, name_case: :random)).to match(
/\A(?:Foo|fOo|foO|FOo|FoO|fOO|FOO)\z/
)
end
end
end
describe "#tag" do
let(:name) { 'div' }
context "when no block or the `text:` keyword argument is given" do
it "must return " do
expect(subject.tag(name)).to eq("<#{name}/>")
end
context "when given a Symbol" do
let(:name) { :div }
it "must return the String version of the Symbol" do
expect(subject.tag(name)).to eq("<#{name}/>")
end
end
context "when given `tag_case: :lower`" do
let(:name) { 'DIV' }
it "must convert the name to lower-case" do
expect(subject.tag(name, tag_case: :lower)).to eq("<#{name.downcase}/>")
end
end
context "when given `tag_case: :upper`" do
it "must convert the name to upper-case" do
expect(subject.tag(name, tag_case: :upper)).to eq("<#{name.upcase}/>")
end
end
context "when given `tag_case: :random`" do
it "must randomize the case of the name" do
expect(subject.tag(name, tag_case: :random)).to match(
/\A<(?:Div|dIv|diV|DIv|DiV|dIV|DIV)\/>\z/
)
end
end
context "when additional attributes are given" do
let(:attr1) { :foo }
let(:value1) { 'bar' }
let(:attr2) { :baz }
let(:value2) { 'qux' }
let(:attrs) do
{attr1 => value1, attr2 => value2}
end
it "must add an attributes list after the tag name" do
expect(subject.tag(name,**attrs)).to eq("<#{name} #{attr1}=\"#{value1}\" #{attr2}=\"#{value2}\"/>")
end
context "when given `attr_case: :lower`" do
let(:attr1) { :FOO }
let(:attr2) { :BAZ }
it "must convert the attribute names to lower-case" do
expect(subject.tag(name, **attrs, attr_case: :lower)).to eq(
"<#{name} #{attr1.downcase}=\"#{value1}\" #{attr2.downcase}=\"#{value2}\"/>"
)
end
end
context "when given `attr_case: :upper`" do
it "must convert the attribute names to upper-case" do
expect(subject.tag(name, **attrs, attr_case: :upper)).to eq(
"<#{name} #{attr1.upcase}=\"#{value1}\" #{attr2.upcase}=\"#{value2}\"/>"
)
end
end
context "when given `attr_case: :random`" do
it "must randomize the case of each attribute name" do
expect(subject.tag(name, **attrs, attr_case: :random)).to match(
/\A<#{name} (?:Foo|fOo|foO|FOo|FoO|fOO|FOO)=\"#{value1}\" (?:Baz|bAz|baZ|BAz|BaZ|bAZ|BAZ)=\"#{value2}\"\/>\z/
)
end
end
context "when given `attr_quote: double`" do
it "must quote the attribute values with double quotes" do
expect(subject.tag(name, **attrs, attr_quote: :double)).to eq(
"<#{name} #{attr1}=\"#{value1}\" #{attr2}=\"#{value2}\"/>"
)
end
context "and when an attribute value contains a double quote" do
let(:value1) { "bar\"baz" }
it "must replace any double quotes with "" do
expect(subject.tag(name, **attrs)).to eq(
"<#{name} #{attr1}=\"bar"baz\" #{attr2}=\"#{value2}\"/>"
)
end
end
end
context "when given `attr_quote: single`" do
it "must quote the attribute values with single quotes" do
expect(subject.tag(name, **attrs, attr_quote: :single)).to eq(
"<#{name} #{attr1}='#{value1}' #{attr2}='#{value2}'/>"
)
end
context "and when an attribute value contains a single quote" do
let(:value1) { "bar'baz" }
it "must replace any double quotes with ';" do
expect(subject.tag(name, **attrs, attr_quote: :single)).to eq(
"<#{name} #{attr1}='bar'baz' #{attr2}='#{value2}'/>"
)
end
end
end
context "when given `attr_quote: :backtick`" do
it "must quote the attribute values with backticks" do
expect(subject.tag(name, **attrs, attr_quote: :backtick)).to eq(
"<#{name} #{attr1}=`#{value1}` #{attr2}=`#{value2}`/>"
)
end
end
context "when given `attr_quote: nil`" do
it "must not quote the attribute values" do
expect(subject.tag(name, **attrs, attr_quote: nil)).to eq(
"<#{name} #{attr1}=#{value1} #{attr2}=#{value2}/>"
)
end
context "and when the value contains a space" do
let(:value1) { "bar baz" }
it "must replace any spaces with nbsp;;" do
expect(subject.tag(name, **attrs, attr_quote: nil)).to eq(
"<#{name} #{attr1}=bar baz #{attr2}=#{value2}/>"
)
end
end
end
end
end
context "when given the `text:` keyword argument" do
let(:inner_text) { 'loren ipsum' }
it "must return ..." do
expect(subject.tag(name, text: inner_text)).to eq(
"<#{name}>#{inner_text}#{name}>"
)
end
context "when given a Symbol" do
let(:name) { :div }
it "must return the String version of the Symbol" do
expect(subject.tag(name, text: inner_text)).to eq(
"<#{name}>#{inner_text}#{name}>"
)
end
end
context "when given `tag_case: :lower`" do
let(:name) { 'DIV' }
it "must convert the tag names to lower-case" do
expect(subject.tag(name, tag_case: :lower, text: inner_text)).to eq(
"<#{name.downcase}>#{inner_text}#{name.downcase}>"
)
end
end
context "when given `tag_case: :upper`" do
it "must convert the tag names to upper-case" do
expect(subject.tag(name, tag_case: :upper, text: inner_text)).to eq(
"<#{name.upcase}>#{inner_text}#{name.upcase}>"
)
end
end
context "when given `tag_case: :random`" do
it "must randomize the case of the tag names" do
expect(subject.tag(name, tag_case: :random, text: inner_text)).to match(
/\A<(?:Div|dIv|diV|DIv|DiV|dIV|DIV)>#{inner_text}<\/(?:Div|dIv|diV|DIv|DiV|dIV|DIV)>\z/
)
end
end
context "when additional attributes are given" do
let(:attr1) { :foo }
let(:value1) { 'bar' }
let(:attr2) { :baz }
let(:value2) { 'qux' }
let(:attrs) do
{attr1 => value1, attr2 => value2}
end
it "must add an attributes list after the tag name" do
expect(subject.tag(name,**attrs, text: inner_text)).to eq(
"<#{name} #{attr1}=\"#{value1}\" #{attr2}=\"#{value2}\">#{inner_text}#{name}>"
)
end
context "when given `attr_case: :lower`" do
let(:attr1) { :FOO }
let(:attr2) { :BAZ }
it "must convert the attribute names to lower-case" do
expect(subject.tag(name, **attrs, attr_case: :lower, text: inner_text)).to eq(
"<#{name} #{attr1.downcase}=\"#{value1}\" #{attr2.downcase}=\"#{value2}\">#{inner_text}#{name}>"
)
end
end
context "when given `attr_case: :upper`" do
it "must convert the attribute names to upper-case" do
expect(subject.tag(name, **attrs, attr_case: :upper, text: inner_text)).to eq(
"<#{name} #{attr1.upcase}=\"#{value1}\" #{attr2.upcase}=\"#{value2}\">#{inner_text}#{name}>"
)
end
end
context "when given `attr_case: :random`" do
it "must randomize the case of each attribute name" do
expect(subject.tag(name, **attrs, attr_case: :random, text: inner_text)).to match(
/\A<#{name} (?:Foo|fOo|foO|FOo|FoO|fOO|FOO)=\"#{value1}\" (?:Baz|bAz|baZ|BAz|BaZ|bAZ|BAZ)=\"#{value2}\">#{inner_text}<\/#{name}>\z/
)
end
end
context "when given `attr_quote: double`" do
it "must quote the attribute values with double quotes" do
expect(subject.tag(name, **attrs, attr_quote: :double, text: inner_text)).to eq(
"<#{name} #{attr1}=\"#{value1}\" #{attr2}=\"#{value2}\">#{inner_text}#{name}>"
)
end
context "and when an attribute value contains a double quote" do
let(:value1) { "bar\"baz" }
it "must replace any double quotes with "" do
expect(subject.tag(name, **attrs, text: inner_text)).to eq(
"<#{name} #{attr1}=\"bar"baz\" #{attr2}=\"#{value2}\">#{inner_text}#{name}>"
)
end
end
end
context "when given `attr_quote: single`" do
it "must quote the attribute values with single quotes" do
expect(subject.tag(name, **attrs, attr_quote: :single, text: inner_text)).to eq(
"<#{name} #{attr1}='#{value1}' #{attr2}='#{value2}'>#{inner_text}#{name}>"
)
end
context "and when an attribute value contains a single quote" do
let(:value1) { "bar'baz" }
it "must replace any double quotes with ';" do
expect(subject.tag(name, **attrs, attr_quote: :single, text: inner_text)).to eq(
"<#{name} #{attr1}='bar'baz' #{attr2}='#{value2}'>#{inner_text}#{name}>"
)
end
end
end
context "when given `attr_quote: :backtick`" do
it "must quote the attribute values with backticks" do
expect(subject.tag(name, **attrs, attr_quote: :backtick, text: inner_text)).to eq(
"<#{name} #{attr1}=`#{value1}` #{attr2}=`#{value2}`>#{inner_text}#{name}>"
)
end
end
context "when given `attr_quote: nil`" do
it "must not quote the attribute values" do
expect(subject.tag(name, **attrs, attr_quote: nil, text: inner_text)).to eq(
"<#{name} #{attr1}=#{value1} #{attr2}=#{value2}>#{inner_text}#{name}>"
)
end
context "and when the value contains a space" do
let(:value1) { "bar baz" }
it "must replace any spaces with nbsp;;" do
expect(subject.tag(name, **attrs, attr_quote: nil, text: inner_text)).to eq(
"<#{name} #{attr1}=bar baz #{attr2}=#{value2}>#{inner_text}#{name}>"
)
end
end
end
end
end
context "when given a block" do
let(:inner_html) { '..." do
expect(subject.tag(name) { inner_html }).to eq(
"<#{name}>#{inner_html}#{name}>"
)
end
context "when given a Symbol" do
let(:name) { :div }
it "must return the String version of the Symbol" do
expect(subject.tag(name) { inner_html }).to eq(
"<#{name}>#{inner_html}#{name}>"
)
end
end
context "when given `tag_case: :lower`" do
let(:name) { 'DIV' }
it "must convert the tag names to lower-case" do
expect(subject.tag(name, tag_case: :lower) { inner_html }).to eq(
"<#{name.downcase}>#{inner_html}#{name.downcase}>"
)
end
end
context "when given `tag_case: :upper`" do
it "must convert the tag names to upper-case" do
expect(subject.tag(name, tag_case: :upper) { inner_html }).to eq(
"<#{name.upcase}>#{inner_html}#{name.upcase}>"
)
end
end
context "when given `tag_case: :random`" do
it "must randomize the case of the tag names" do
expect(subject.tag(name, tag_case: :random) { inner_html }).to match(
/\A<(?:Div|dIv|diV|DIv|DiV|dIV|DIV)>#{inner_html}<\/(?:Div|dIv|diV|DIv|DiV|dIV|DIV)>\z/
)
end
end
context "when additional attributes are given" do
let(:attr1) { :foo }
let(:value1) { 'bar' }
let(:attr2) { :baz }
let(:value2) { 'qux' }
let(:attrs) do
{attr1 => value1, attr2 => value2}
end
it "must add an attributes list after the tag name" do
expect(subject.tag(name,**attrs) { inner_html }).to eq(
"<#{name} #{attr1}=\"#{value1}\" #{attr2}=\"#{value2}\">#{inner_html}#{name}>"
)
end
context "when given `attr_case: :lower`" do
let(:attr1) { :FOO }
let(:attr2) { :BAZ }
it "must convert the attribute names to lower-case" do
expect(subject.tag(name, **attrs, attr_case: :lower) { inner_html }).to eq(
"<#{name} #{attr1.downcase}=\"#{value1}\" #{attr2.downcase}=\"#{value2}\">#{inner_html}#{name}>"
)
end
end
context "when given `attr_case: :upper`" do
it "must convert the attribute names to upper-case" do
expect(subject.tag(name, **attrs, attr_case: :upper) { inner_html }).to eq(
"<#{name} #{attr1.upcase}=\"#{value1}\" #{attr2.upcase}=\"#{value2}\">#{inner_html}#{name}>"
)
end
end
context "when given `attr_case: :random`" do
it "must randomize the case of each attribute name" do
expect(subject.tag(name, **attrs, attr_case: :random) { inner_html }).to match(
/\A<#{name} (?:Foo|fOo|foO|FOo|FoO|fOO|FOO)=\"#{value1}\" (?:Baz|bAz|baZ|BAz|BaZ|bAZ|BAZ)=\"#{value2}\">#{inner_html}<\/#{name}>\z/
)
end
end
context "when given `attr_quote: double`" do
it "must quote the attribute values with double quotes" do
expect(subject.tag(name, **attrs, attr_quote: :double) { inner_html }).to eq(
"<#{name} #{attr1}=\"#{value1}\" #{attr2}=\"#{value2}\">#{inner_html}#{name}>"
)
end
context "and when an attribute value contains a double quote" do
let(:value1) { "bar\"baz" }
it "must replace any double quotes with "" do
expect(subject.tag(name, **attrs) { inner_html }).to eq(
"<#{name} #{attr1}=\"bar"baz\" #{attr2}=\"#{value2}\">#{inner_html}#{name}>"
)
end
end
end
context "when given `attr_quote: single`" do
it "must quote the attribute values with single quotes" do
expect(subject.tag(name, **attrs, attr_quote: :single) { inner_html }).to eq(
"<#{name} #{attr1}='#{value1}' #{attr2}='#{value2}'>#{inner_html}#{name}>"
)
end
context "and when an attribute value contains a single quote" do
let(:value1) { "bar'baz" }
it "must replace any double quotes with ';" do
expect(subject.tag(name, **attrs, attr_quote: :single) { inner_html }).to eq(
"<#{name} #{attr1}='bar'baz' #{attr2}='#{value2}'>#{inner_html}#{name}>"
)
end
end
end
context "when given `attr_quote: :backtick`" do
it "must quote the attribute values with backticks" do
expect(subject.tag(name, **attrs, attr_quote: :backtick) { inner_html }).to eq(
"<#{name} #{attr1}=`#{value1}` #{attr2}=`#{value2}`>#{inner_html}#{name}>"
)
end
end
context "when given `attr_quote: nil`" do
it "must not quote the attribute values" do
expect(subject.tag(name, **attrs, attr_quote: nil) { inner_html }).to eq(
"<#{name} #{attr1}=#{value1} #{attr2}=#{value2}>#{inner_html}#{name}>"
)
end
context "and when the value contains a space" do
let(:value1) { "bar baz" }
it "must replace any spaces with nbsp;;" do
expect(subject.tag(name, **attrs, attr_quote: nil) { inner_html }).to eq(
"<#{name} #{attr1}=bar baz #{attr2}=#{value2}>#{inner_html}#{name}>"
)
end
end
end
end
end
end
end