From 87bd31f601cc167b055694100b25ade6261c9c59 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Thu, 6 Jul 2023 08:27:33 -0400 Subject: [PATCH 1/5] Add .rdoc_options to make README the front page. and minor cleanup in the README --- .rdoc_options | 10 ++++++++++ README.md | 35 +++++++++++++++-------------------- 2 files changed, 25 insertions(+), 20 deletions(-) create mode 100644 .rdoc_options diff --git a/.rdoc_options b/.rdoc_options new file mode 100644 index 0000000..6681b08 --- /dev/null +++ b/.rdoc_options @@ -0,0 +1,10 @@ +--- +encoding: UTF-8 +charset: UTF-8 +exclude: +- "\\.gemspec\\z" +- "gemfiles" +- "Gemfile*" +- "Rakefile" +main_page: "README.md" +markup: rdoc diff --git a/README.md b/README.md index 6d62cf3..d333ab3 100644 --- a/README.md +++ b/README.md @@ -5,26 +5,6 @@ Doms are compared via `assert_dom_equal` and `assert_dom_not_equal`. Elements are asserted via `assert_dom`, `assert_dom_encoded`, `assert_dom_email` and a subset of the dom can be selected with `css_select`. The gem is developed for Rails 4.2 and above, and will not work on previous versions. -## Nokogiri::CSS::SyntaxError exceptions when upgrading to Rails 4.2: - -Nokogiri is slightly stricter about the format of CSS selectors than the previous implementation. - -Check the 4.2 release notes [section on `assert_select`](http://edgeguides.rubyonrails.org/4_2_release_notes.html#assert-select) for help. - -## Installation - -Add this line to your application's Gemfile: - - gem 'rails-dom-testing' - -And then execute: - - $ bundle - -Or install it yourself as: - - $ gem install rails-dom-testing - ## Usage ### Dom Assertions @@ -53,6 +33,21 @@ assert_dom_email '#you-got-mail' The documentation in [selector_assertions.rb](https://github.com/rails/rails-dom-testing/blob/master/lib/rails/dom/testing/assertions/selector_assertions.rb) goes into a lot more detail of how selector assertions can be used. + +## Installation + +Add this line to your application's Gemfile: + + gem 'rails-dom-testing' + +And then execute: + + $ bundle + +Or install it yourself as: + + $ gem install rails-dom-testing + ## Read more Under the hood the doms are parsed with Nokogiri, and you'll generally be working with these two classes: From 1c306c5cfa1c71dc8e53322184539a4038b7fe60 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Wed, 5 Jul 2023 16:55:52 -0400 Subject: [PATCH 2/5] feat: Introduce Rails::Dom::Testing.default_html_version Also provide helper methods: - `Rails::Dom::Testing.html_document` - `Rails::Dom::Testing.html_document_fragment` which will return a parser class based on the default or an optional injected `html_version:` kwarg. These methods will raise an exception if the configuration cannot be honored (e.g., the HTML5 parser isn't supported on the platform). --- lib/rails/dom/testing/parser_selection.rb | 49 +++++++++++++++ test/parser_selection_test.rb | 76 +++++++++++++++++++++++ test/test_helper.rb | 12 ++++ 3 files changed, 137 insertions(+) create mode 100644 lib/rails/dom/testing/parser_selection.rb create mode 100644 test/parser_selection_test.rb diff --git a/lib/rails/dom/testing/parser_selection.rb b/lib/rails/dom/testing/parser_selection.rb new file mode 100644 index 0000000..336a703 --- /dev/null +++ b/lib/rails/dom/testing/parser_selection.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require "active_support" +require "active_support/core_ext/module/attribute_accessors" + +module Rails + module Dom + module Testing + mattr_accessor :default_html_version, default: :html4 + + class << self + def html5_support? + defined?(Nokogiri::HTML5) + end + + def html_document(html_version: nil) + parser_classes = { html4: Nokogiri::HTML4::Document } + parser_classes[:html5] = Nokogiri::HTML5::Document if html5_support? + + choose_html_parser(parser_classes, html_version: html_version) + end + + def html_document_fragment(html_version: nil) + parser_classes = { html4: Nokogiri::HTML4::DocumentFragment } + parser_classes[:html5] = Nokogiri::HTML5::DocumentFragment if html5_support? + + choose_html_parser(parser_classes, html_version: html_version) + end + + private + def choose_html_parser(parser_classes, html_version: nil) + html_version ||= Rails::Dom::Testing.default_html_version + + case html_version + when :html4 + parser_classes[:html4] + when :html5 + unless Rails::Dom::Testing.html5_support? + raise NotImplementedError, "html5 parser is not supported on this platform" + end + parser_classes[:html5] + else + raise ArgumentError, "html_version must be :html4 or :html5, received #{html_version.inspect}" + end + end + end + end + end +end diff --git a/test/parser_selection_test.rb b/test/parser_selection_test.rb new file mode 100644 index 0000000..afb064c --- /dev/null +++ b/test/parser_selection_test.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +require "test_helper" +require "rails-dom-testing" + +class DomTestingParserSelectionTest < ActiveSupport::TestCase + include DomTestingHelpers + + test "with default html4" do + with_default_html_version(:html4) do + assert_equal(Nokogiri::HTML4::Document, Rails::Dom::Testing.html_document) + assert_equal(Nokogiri::HTML4::DocumentFragment, Rails::Dom::Testing.html_document_fragment) + + assert_equal(Nokogiri::HTML4::Document, Rails::Dom::Testing.html_document(html_version: :html4)) + assert_equal(Nokogiri::HTML4::DocumentFragment, Rails::Dom::Testing.html_document_fragment(html_version: :html4)) + + if Rails::Dom::Testing.html5_support? + assert_equal(Nokogiri::HTML5::Document, Rails::Dom::Testing.html_document(html_version: :html5)) + assert_equal(Nokogiri::HTML5::DocumentFragment, Rails::Dom::Testing.html_document_fragment(html_version: :html5)) + else + assert_raises(NotImplementedError) { Rails::Dom::Testing.html_document(html_version: :html5) } + assert_raises(NotImplementedError) { Rails::Dom::Testing.html_document_fragment(html_version: :html5) } + end + + assert_raises(ArgumentError) { Rails::Dom::Testing.html_document(html_version: :html9) } + assert_raises(ArgumentError) { Rails::Dom::Testing.html_document_fragment(html_version: :html9) } + end + end + + test "with default html5" do + with_default_html_version(:html5) do + if Rails::Dom::Testing.html5_support? + assert_equal(Nokogiri::HTML5::Document, Rails::Dom::Testing.html_document) + assert_equal(Nokogiri::HTML5::DocumentFragment, Rails::Dom::Testing.html_document_fragment) + else + assert_raises(NotImplementedError) { Rails::Dom::Testing.html_document } + assert_raises(NotImplementedError) { Rails::Dom::Testing.html_document_fragment } + end + + assert_equal(Nokogiri::HTML4::Document, Rails::Dom::Testing.html_document(html_version: :html4)) + assert_equal(Nokogiri::HTML4::DocumentFragment, Rails::Dom::Testing.html_document_fragment(html_version: :html4)) + + if Rails::Dom::Testing.html5_support? + assert_equal(Nokogiri::HTML5::Document, Rails::Dom::Testing.html_document(html_version: :html5)) + assert_equal(Nokogiri::HTML5::DocumentFragment, Rails::Dom::Testing.html_document_fragment(html_version: :html5)) + else + assert_raises(NotImplementedError) { Rails::Dom::Testing.html_document(html_version: :html5) } + assert_raises(NotImplementedError) { Rails::Dom::Testing.html_document_fragment(html_version: :html5) } + end + + assert_raises(ArgumentError) { Rails::Dom::Testing.html_document(html_version: :html9) } + assert_raises(ArgumentError) { Rails::Dom::Testing.html_document_fragment(html_version: :html9) } + end + end + + test "with invalid default" do + with_default_html_version(:html8) do + assert_raises(ArgumentError) { Rails::Dom::Testing.html_document } + assert_raises(ArgumentError) { Rails::Dom::Testing.html_document_fragment } + + assert_equal(Nokogiri::HTML4::Document, Rails::Dom::Testing.html_document(html_version: :html4)) + assert_equal(Nokogiri::HTML4::DocumentFragment, Rails::Dom::Testing.html_document_fragment(html_version: :html4)) + + if Rails::Dom::Testing.html5_support? + assert_equal(Nokogiri::HTML5::Document, Rails::Dom::Testing.html_document(html_version: :html5)) + assert_equal(Nokogiri::HTML5::DocumentFragment, Rails::Dom::Testing.html_document_fragment(html_version: :html5)) + else + assert_raises(NotImplementedError) { Rails::Dom::Testing.html_document(html_version: :html5) } + assert_raises(NotImplementedError) { Rails::Dom::Testing.html_document_fragment(html_version: :html5) } + end + + assert_raises(ArgumentError) { Rails::Dom::Testing.html_document(html_version: :html9) } + assert_raises(ArgumentError) { Rails::Dom::Testing.html_document_fragment(html_version: :html9) } + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 56edc8e..5c4b173 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -6,3 +6,15 @@ require "minitest/autorun" ActiveSupport::TestCase.test_order = :random + +module DomTestingHelpers + def with_default_html_version(version) + old_version = Rails::Dom::Testing.default_html_version + begin + Rails::Dom::Testing.default_html_version = version + yield + ensure + Rails::Dom::Testing.default_html_version = old_version + end + end +end From cb05bb7cf6a04244806360aed0992beb45ec92da Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Thu, 6 Jul 2023 08:47:55 -0400 Subject: [PATCH 3/5] feat: some assertions allow setting the HTML parser version via an `html_version` kwarg: - assert_dom_equal and assert_dom_not_equal - assert_dom_encoded - assert_dom_email The remaining assertions all rely on `document_root_element` to return the DOM (meaning we'll have to make changes to Rails). --- .../dom/testing/assertions/dom_assertions.rb | 14 +-- .../testing/assertions/selector_assertions.rb | 9 +- test/dom_assertions_test.rb | 87 +++++++++++++++++++ test/selector_assertions_test.rb | 49 ++++++++++- test/test_helper.rb | 4 + 5 files changed, 152 insertions(+), 11 deletions(-) diff --git a/lib/rails/dom/testing/assertions/dom_assertions.rb b/lib/rails/dom/testing/assertions/dom_assertions.rb index 2b32376..036d2aa 100644 --- a/lib/rails/dom/testing/assertions/dom_assertions.rb +++ b/lib/rails/dom/testing/assertions/dom_assertions.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require_relative "../parser_selection" + module Rails module Dom module Testing @@ -9,8 +11,8 @@ module DomAssertions # # # assert that the referenced method generates the appropriate HTML string # assert_dom_equal 'Apples', link_to("Apples", "http://www.example.com") - def assert_dom_equal(expected, actual, message = nil, strict: false) - expected_dom, actual_dom = fragment(expected), fragment(actual) + def assert_dom_equal(expected, actual, message = nil, strict: false, html_version: nil) + expected_dom, actual_dom = fragment(expected, html_version: html_version), fragment(actual, html_version: html_version) message ||= "Expected: #{expected}\nActual: #{actual}" assert compare_doms(expected_dom, actual_dom, strict), message end @@ -19,8 +21,8 @@ def assert_dom_equal(expected, actual, message = nil, strict: false) # # # assert that the referenced method does not generate the specified HTML string # assert_dom_not_equal 'Apples', link_to("Oranges", "http://www.example.com") - def assert_dom_not_equal(expected, actual, message = nil, strict: false) - expected_dom, actual_dom = fragment(expected), fragment(actual) + def assert_dom_not_equal(expected, actual, message = nil, strict: false, html_version: nil) + expected_dom, actual_dom = fragment(expected, html_version: html_version), fragment(actual, html_version: html_version) message ||= "Expected: #{expected}\nActual: #{actual}" assert_not compare_doms(expected_dom, actual_dom, strict), message end @@ -84,8 +86,8 @@ def equal_attribute?(attr, other_attr) end private - def fragment(text) - Nokogiri::HTML::DocumentFragment.parse(text) + def fragment(text, html_version: nil) + Rails::Dom::Testing.html_document_fragment(html_version: html_version).parse(text) end end end diff --git a/lib/rails/dom/testing/assertions/selector_assertions.rb b/lib/rails/dom/testing/assertions/selector_assertions.rb index 31b8145..016eff5 100644 --- a/lib/rails/dom/testing/assertions/selector_assertions.rb +++ b/lib/rails/dom/testing/assertions/selector_assertions.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require_relative "../parser_selection" require_relative "selector_assertions/count_describable" require_relative "selector_assertions/html_selector" @@ -212,7 +213,7 @@ def assert_dom(*args, &block) # end # end # end - def assert_dom_encoded(element = nil, &block) + def assert_dom_encoded(element = nil, html_version: nil, &block) if !element && !@selected raise ArgumentError, "Element is required when called from a nonnested assert_dom" end @@ -223,7 +224,7 @@ def assert_dom_encoded(element = nil, &block) end.map(&:content) end.join - selected = Nokogiri::HTML::DocumentFragment.parse(content) + selected = Rails::Dom::Testing.html_document_fragment(html_version: html_version).parse(content) nest_selection(selected) do if content.empty? yield selected @@ -249,14 +250,14 @@ def assert_dom_encoded(element = nil, &block) # # Work with items here... # end # end - def assert_dom_email(&block) + def assert_dom_email(html_version: nil, &block) deliveries = ActionMailer::Base.deliveries assert !deliveries.empty?, "No e-mail in delivery list" deliveries.each do |delivery| (delivery.parts.empty? ? [delivery] : delivery.parts).each do |part| if /^text\/html\W/.match?(part["Content-Type"].to_s) - root = Nokogiri::HTML::DocumentFragment.parse(part.body.to_s) + root = Rails::Dom::Testing.html_document_fragment(html_version: html_version).parse(part.body.to_s) assert_dom root, ":root", &block end end diff --git a/test/dom_assertions_test.rb b/test/dom_assertions_test.rb index 24e11da..e37d22f 100644 --- a/test/dom_assertions_test.rb +++ b/test/dom_assertions_test.rb @@ -125,3 +125,90 @@ def test_dom_not_equal_with_interior_whitespace assert_dom_not_equal(with_space, without_space) end end + +class DomAssertionsHtmlParserSelectionTest < ActiveSupport::TestCase + include DomTestingHelpers + include Rails::Dom::Testing::Assertions::DomAssertions + + def setup + super + + # https://html.spec.whatwg.org/multipage/parsing.html#an-introduction-to-error-handling-and-strange-cases-in-the-parser + # we use these results to assert that we're invoking the expected parser. + @input = "

12345

" + @html4_result = jruby? ? "

12345

" : "

12345

" + @html5_result = jruby? ? nil : "

12345

" + end + + test "default value is html4" do + assert_equal(:html4, Rails::Dom::Testing.default_html_version) + end + + test "default html4, no version specified" do + with_default_html_version(:html4) do + assert_dom_equal(@html4_result, @input) + assert_dom_not_equal(@html5_result, @input) + end + end + + test "default html4, html4 specified" do + with_default_html_version(:html4) do + assert_dom_equal(@html4_result, @input, html_version: :html4) + assert_dom_not_equal(@html5_result, @input, html_version: :html4) + end + end + + test "default html4, html5 specified" do + skip("html5 is not supported") unless Rails::Dom::Testing.html5_support? + + with_default_html_version(:html4) do + assert_dom_equal(@html5_result, @input, html_version: :html5) + assert_dom_not_equal(@html4_result, @input, html_version: :html5) + end + end + + test "default html5, no version specified" do + skip("html5 is not supported") unless Rails::Dom::Testing.html5_support? + + with_default_html_version(:html5) do + assert_dom_equal(@html5_result, @input) + assert_dom_not_equal(@html4_result, @input) + end + end + + test "default html5, html4 specified" do + with_default_html_version(:html5) do + assert_dom_equal(@html4_result, @input, html_version: :html4) + assert_dom_not_equal(@html5_result, @input, html_version: :html4) + end + end + + test "default html5, html5 specified" do + skip("html5 is not supported") unless Rails::Dom::Testing.html5_support? + + with_default_html_version(:html5) do + assert_dom_equal(@html5_result, @input, html_version: :html5) + assert_dom_not_equal(@html4_result, @input, html_version: :html5) + end + end + + test "raise NotImplementedError html5 when not supported" do + Rails::Dom::Testing.stub(:html5_support?, false) do + with_default_html_version(:html5) do + assert_raises(NotImplementedError) { assert_dom_equal("a", "b") } + assert_raises(NotImplementedError) { assert_dom_equal("a", "b", html_version: :html5) } + assert_nothing_raised { assert_dom_equal(@html4_result, @input, html_version: :html4) } + end + end + end + + test "default set to invalid" do + with_default_html_version(:html9) do + assert_raises(ArgumentError) { assert_dom_equal("a", "b") } + end + end + + test "invalid version specified" do + assert_raises(ArgumentError) { assert_dom_equal("a", "b", html_version: :html9) } + end +end diff --git a/test/selector_assertions_test.rb b/test/selector_assertions_test.rb index 0089aee..5ba15f0 100644 --- a/test/selector_assertions_test.rb +++ b/test/selector_assertions_test.rb @@ -7,6 +7,7 @@ class AssertSelectTest < ActiveSupport::TestCase Assertion = Minitest::Assertion + include DomTestingHelpers include Rails::Dom::Testing::Assertions::SelectorAssertions def assert_failure(message, &block) @@ -302,6 +303,52 @@ def test_feed_item_encoded end end + def test_feed_item_encoded_with_html_version + # https://html.spec.whatwg.org/multipage/parsing.html#an-introduction-to-error-handling-and-strange-cases-in-the-parser + # we use these results to assert that we're invoking the expected parser. + input = CGI.escapeHTML("

12345

") + html4_result = jruby? ? "

12345

" : "

12345

" + html5_result = jruby? ? nil : "

12345

" + + render_xml(<<~XML) + + #{input} + + XML + + with_default_html_version(:html4) do + assert_select "root contents" do + assert_select_encoded do |contents| + assert_equal(html4_result, contents.to_html) + end + + assert_select_encoded(html_version: :html4) do |contents| + assert_equal(html4_result, contents.to_html) + end + + assert_select_encoded(html_version: :html5) do |contents| + assert_equal(html5_result, contents.to_html) + end if Rails::Dom::Testing.html5_support? + end + end + + with_default_html_version(:html5) do + assert_select "root contents" do + assert_select_encoded do |contents| + assert_equal(html5_result, contents.to_html) + end if Rails::Dom::Testing.html5_support? + + assert_select_encoded(html_version: :html4) do |contents| + assert_equal(html4_result, contents.to_html) + end + + assert_select_encoded(html_version: :html5) do |contents| + assert_equal(html5_result, contents.to_html) + end if Rails::Dom::Testing.html5_support? + end + end + end + def test_body_not_present_in_empty_document render_html "
" assert_select "body", 0 @@ -348,7 +395,7 @@ def fake_render(content_type, content) @html_document = if content_type == :xml Nokogiri::XML::Document.parse(content) else - Nokogiri::HTML::Document.parse(content) + Rails::Dom::Testing.html_document.parse(content) end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 5c4b173..3b52807 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -8,6 +8,10 @@ ActiveSupport::TestCase.test_order = :random module DomTestingHelpers + def jruby? + !! Nokogiri.jruby? + end + def with_default_html_version(version) old_version = Rails::Dom::Testing.default_html_version begin From 123af88387d5e03852af1073c45691befc101709 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Thu, 6 Jul 2023 13:48:26 -0400 Subject: [PATCH 4/5] feat: railtie to set Rails::Dom::Testing.default_html_version based on Rails' config.dom_testing_default_html_version --- lib/rails/dom/testing/parser_selection.rb | 2 ++ lib/rails/dom/testing/railtie.rb | 14 ++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 lib/rails/dom/testing/railtie.rb diff --git a/lib/rails/dom/testing/parser_selection.rb b/lib/rails/dom/testing/parser_selection.rb index 336a703..648f8ee 100644 --- a/lib/rails/dom/testing/parser_selection.rb +++ b/lib/rails/dom/testing/parser_selection.rb @@ -47,3 +47,5 @@ def choose_html_parser(parser_classes, html_version: nil) end end end + +require_relative "railtie" if defined?(Rails::Railtie) diff --git a/lib/rails/dom/testing/railtie.rb b/lib/rails/dom/testing/railtie.rb new file mode 100644 index 0000000..4dadcc3 --- /dev/null +++ b/lib/rails/dom/testing/railtie.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Rails + module Dom + module Testing + class Railtie < Rails::Railtie # :nodoc: + config.after_initialize do |app| + version = app.config.try(:dom_testing_default_html_version) # Rails 7.1+ + Rails::Dom::Testing.default_html_version = version if version + end + end + end + end +end From 144f8e573c4723d293ef9ecbf14f4747a8fcdefc Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Thu, 6 Jul 2023 15:14:59 -0400 Subject: [PATCH 5/5] doc: update documentation to include HTML parser selection --- README.md | 24 +++++++++ .../dom/testing/assertions/dom_assertions.rb | 50 +++++++++++++++++- .../testing/assertions/selector_assertions.rb | 52 +++++++++++++++---- 3 files changed, 115 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index d333ab3..9999846 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,30 @@ assert_dom_email '#you-got-mail' The documentation in [selector_assertions.rb](https://github.com/rails/rails-dom-testing/blob/master/lib/rails/dom/testing/assertions/selector_assertions.rb) goes into a lot more detail of how selector assertions can be used. +### HTML versions + +By default, assertions will use Nokogiri's HTML4 parser. + +If `Rails::Dom::Testing.default_html_version` is set to `:html5`, then the assertions will use +Nokogiri's HTML5 parser. (If the HTML5 parser is not available on your platform, then a +`NotImplementedError` will be raised.) + +When testing in a Rails application, the parser default can also be set by setting +`Rails.application.config.dom_testing_default_html_version`. + +Some assertions support an `html_version:` keyword argument which can override the default for that +assertion. For example: + +``` ruby +# compare DOMs built with the HTML5 parser +assert_dom_equal(expected, actual, html_version: :html5) + +# compare DOMs built with the HTML4 parser +assert_dom_not_equal(expected, actual, html_version: :html4) +``` + +Please see documentation for individual assertions for more details. + ## Installation diff --git a/lib/rails/dom/testing/assertions/dom_assertions.rb b/lib/rails/dom/testing/assertions/dom_assertions.rb index 036d2aa..95795ed 100644 --- a/lib/rails/dom/testing/assertions/dom_assertions.rb +++ b/lib/rails/dom/testing/assertions/dom_assertions.rb @@ -10,7 +10,30 @@ module DomAssertions # \Test two HTML strings for equivalency (e.g., equal even when attributes are in another order) # # # assert that the referenced method generates the appropriate HTML string - # assert_dom_equal 'Apples', link_to("Apples", "http://www.example.com") + # assert_dom_equal( + # 'Apples', + # link_to("Apples", "http://www.example.com"), + # ) + # + # By default, the matcher will not pay attention to whitespace in text nodes (e.g., spaces + # and newlines). If you want stricter matching with exact matching for whitespace, pass + # strict: true: + # + # # these assertions will both pass + # assert_dom_equal "
\nfoo\n\
", "
foo
", strict: false + # assert_dom_not_equal "
\nfoo\n\
", "
foo
", strict: true + # + # The DOMs are created using an HTML parser specified by + # Rails::Dom::Testing.default_html_version (either :html4 or :html5). + # + # When testing in a Rails application, the parser default can also be set by setting + # +Rails.application.config.dom_testing_default_html_version+. + # + # If you want to specify the HTML parser just for a particular assertion, pass + # html_version: :html4 or html_version: :html5 keyword arguments: + # + # assert_dom_equal expected, actual, html_version: :html5 + # def assert_dom_equal(expected, actual, message = nil, strict: false, html_version: nil) expected_dom, actual_dom = fragment(expected, html_version: html_version), fragment(actual, html_version: html_version) message ||= "Expected: #{expected}\nActual: #{actual}" @@ -20,7 +43,30 @@ def assert_dom_equal(expected, actual, message = nil, strict: false, html_versio # The negated form of +assert_dom_equal+. # # # assert that the referenced method does not generate the specified HTML string - # assert_dom_not_equal 'Apples', link_to("Oranges", "http://www.example.com") + # assert_dom_not_equal( + # 'Apples', + # link_to("Oranges", "http://www.example.com"), + # ) + # + # By default, the matcher will not pay attention to whitespace in text nodes (e.g., spaces + # and newlines). If you want stricter matching with exact matching for whitespace, pass + # strict: true: + # + # # these assertions will both pass + # assert_dom_equal "
\nfoo\n\
", "
foo
", strict: false + # assert_dom_not_equal "
\nfoo\n\
", "
foo
", strict: true + # + # The DOMs are created using an HTML parser specified by + # Rails::Dom::Testing.default_html_version (either :html4 or :html5). + # + # When testing in a Rails application, the parser default can also be set by setting + # +Rails.application.config.dom_testing_default_html_version+. + # + # If you want to specify the HTML parser just for a particular assertion, pass + # html_version: :html4 or html_version: :html5 keyword arguments: + # + # assert_dom_not_equal expected, actual, html_version: :html5 + # def assert_dom_not_equal(expected, actual, message = nil, strict: false, html_version: nil) expected_dom, actual_dom = fragment(expected, html_version: html_version), fragment(actual, html_version: html_version) message ||= "Expected: #{expected}\nActual: #{actual}" diff --git a/lib/rails/dom/testing/assertions/selector_assertions.rb b/lib/rails/dom/testing/assertions/selector_assertions.rb index 016eff5..2a7c319 100644 --- a/lib/rails/dom/testing/assertions/selector_assertions.rb +++ b/lib/rails/dom/testing/assertions/selector_assertions.rb @@ -213,6 +213,24 @@ def assert_dom(*args, &block) # end # end # end + # + # The DOM is created using an HTML parser specified by + # Rails::Dom::Testing.default_html_version (either :html4 or :html5). + # + # When testing in a Rails application, the parser default can also be set by setting + # +Rails.application.config.dom_testing_default_html_version+. + # + # If you want to specify the HTML parser just for a particular assertion, pass + # html_version: :html4 or html_version: :html5 keyword arguments: + # + # assert_dom "feed[xmlns='http://www.w3.org/2005/Atom']" do + # assert_dom "entry>title" do + # assert_dom_encoded(html_version: :html5) do + # assert_dom "b" + # end + # end + # end + # def assert_dom_encoded(element = nil, html_version: nil, &block) if !element && !@selected raise ArgumentError, "Element is required when called from a nonnested assert_dom" @@ -240,16 +258,32 @@ def assert_dom_encoded(element = nil, html_version: nil, &block) # You must enable deliveries for this assertion to work, use: # ActionMailer::Base.perform_deliveries = true # - # assert_dom_email do - # assert_dom "h1", "Email alert" - # end + # Example usage: + # + # assert_dom_email do + # assert_dom "h1", "Email alert" + # end + # + # assert_dom_email do + # items = assert_dom "ol>li" + # items.each do + # # Work with items here... + # end + # end + # + # The DOM is created using an HTML parser specified by + # Rails::Dom::Testing.default_html_version (either :html4 or :html5). + # + # When testing in a Rails application, the parser default can also be set by setting + # +Rails.application.config.dom_testing_default_html_version+. + # + # If you want to specify the HTML parser just for a particular assertion, pass + # html_version: :html4 or html_version: :html5 keyword arguments: + # + # assert_dom_email(html_version: :html5) do + # assert_dom "h1", "Email alert" + # end # - # assert_dom_email do - # items = assert_dom "ol>li" - # items.each do - # # Work with items here... - # end - # end def assert_dom_email(html_version: nil, &block) deliveries = ActionMailer::Base.deliveries assert !deliveries.empty?, "No e-mail in delivery list"