# NAME Test2::Tools::DOM - Tools to test HTML/XML-based DOM representations # SYNOPSIS use Test2::V0; use Test2::Tools::DOM; my $html = <<'HTML'; A test document

Some text

HTML is $html, dom { children bag { item dom { tag 'body' }; item dom { tag 'head' }; end; }; at 'link[rel=icon]' => dom { attr href => 'favicon.ico' }; find '.paragraph' => array { item dom { text 'Some text' }; end; }; }; done_testing; # DESCRIPTION Test2::Tools::DOM exports a set of testing functions designed to make it easier to write declarative tests for XML-based DOM representations. This will most commonly be HTML documents, but it can include other similar types of documents (eg. SVG images, other XML documents, etc). # FUNCTIONS Unless otherwise stated, the functions described in this section are exported by default by this distribution. Most of the heavy lifting behind the scenes is done by [Mojo::DOM58](https://metacpan.org/pod/Mojo%3A%3ADOM58), and most of the functions described below are thin wrappers around the methods in that class with the same names. Likewise, several of them support [CSS selectors](https://metacpan.org/pod/Mojo::DOM58#SELECTORS) for filtering the elements they will return. Please refer to [that distribution's documentation](https://metacpan.org/pod/Mojo%3A%3ADOM58) for additional details. ## dom dom { ... } Starts a new DOM testing context. It takes a single block, inside which the rest of the functions described in this section can be used. It can be used as the check in any [Test2](https://metacpan.org/pod/Test2) testing method. The input can either be a [Mojo::DOM58](https://metacpan.org/pod/Mojo%3A%3ADOM58) object, or a string with the text representation of the DOM, which will be passed to the [Mojo::DOM58](https://metacpan.org/pod/Mojo%3A%3ADOM58) constructor. For convenience, if the input is at the root node of the DOM tree, it will be advanced to its first child element, if one exists. ## all\_text all_text CHECK Takes a check only. Extracts the text content from all descendants of this element (by calling ['all\_text' on the Mojo::DOM58 object](https://metacpan.org/pod/Mojo%3A%3ADOM58#all_text)), and this is passed to the provided check. is '

Hello, World!

', dom { all_text 'Hello, World!'; # OK: includes text in descendants text 'Hello, '; # OK: use text for the text of this element only }; ## at at SELECTOR, CHECK Takes a selector and a check. The selector is used to find the first matching descendant (by calling ['at' on the Mojo::DOM58 object](https://metacpan.org/pod/Mojo%3A%3ADOM58#at)), and this is passed to the provided check. The [Test2 existence checks](https://metacpan.org/pod/Test2::Tools::Compare/QUICK-CHECKS) can be used to check whether a given selector matches or not. is '
', dom { attr id => 'a'; # OK, we start at #a at '#b' => dom { attr id => 'b'; # OK, we've moved to #b }; at '#c' => DNE; # OK, this element does not exist # A missing element matches U, F, and DNE # A present element matches D, T, and E }; ## attr attr CHECK attr NAME, CHECK Takes either a single check, or the name of an attribute and a check. When called without a name, all attributes are fetched and passed to the check as a hashref (by calling ['attr' on the Mojo::DOM58 object](https://metacpan.org/pod/Mojo%3A%3ADOM58#attr)), and this is passed to the provided check. When called with a name, only the attribute with that name will be read and passed to the check. is '', dom { # Get a hashref with all attributes # Hashref is then checked using standard Perl logic attr hash { field type => 'checkbox'; field name => 'answer'; field value => 42; field checked => E; # OK: the attribute exists field checked => U; # OK: the attribute has no value field checked => F; # OK: undefined is false in Perl-land end; }; }; When fetching a single value, the [Test2 boolean and existence checks](https://metacpan.org/pod/Test2::Tools::Compare/QUICK-CHECKS) will be interpreted using XML-logic rather than Perl-logic: an attribute without a value in the DOM will be undefined but true. is '', dom { attr type => 'checkbox'; attr name => 'answer'; attr value => 42; # When fetching individual attributes, checks use XML-logic attr checked => E; # OK: the attribute exists attr checked => U; # OK: the attribute has no value, so it's undefined attr checked => T; # OK: the attribute is present, so it's true }; ## call call NAME, CHECK call [ NAME, ARGUMENTS ], CHECK call CODEREF, CHECK call_list ... call_hash ... _Supported from version 0.004003_. Within the test context created by the ["dom"](#dom) keyword the 'call' family of keywords provided by [Test2::Tools::Compare](https://metacpan.org/pod/Test2%3A%3ATools%3A%3ACompare) can be used to make calls on the underlying [Mojo::DOM58](https://metacpan.org/pod/Mojo%3A%3ADOM58) object as if the test were using the [object builder](https://metacpan.org/pod/Test2%3A%3ATools%3A%3ACompare#OBJECT-BUILDER). Please refer to the documentation in that distribution for more details on how to use this keyword. Since this is a core function from [Test2::Suite](https://metacpan.org/pod/Test2%3A%3ASuite), it will not be exported by this distribution. ## children children CHECK children SELECTOR, CHECK Takes either a single check, or a selector and a check. When called without a selector, all direct children of the current element will be passed to the check as a possibly empty arrayref (by calling ['children' on the Mojo::DOM58 object](https://metacpan.org/pod/Mojo%3A%3ADOM58#children)). When called with a selector, only children that match will be passed to the check. is '

Text

  1. A
  2. B
', dom { children [ # First child is

dom { tag 'p' }, # Second child is

    dom { tag 'ol'; children li => [ dom { text 'A' }, dom { text 'B' }, ]; }, ]; }; ## content content CHECK Takes a check only. Extracts the raw content from this element and all its descendants (by calling ['content' on the Mojo::DOM58 object](https://metacpan.org/pod/Mojo%3A%3ADOM58#content)), and this is passed to the provided check. is '
    Hello, World!
    ', dom { content 'Hello, World!'; at em => dom { content 'World!' }; }; ## find find SELECTOR, CHECK Takes a selector and a check. The selector will be used to find all the matching descendants of this elements, which will be passed to the check as a possibly empty arrayref (by calling ['find' on the Mojo::DOM58 object](https://metacpan.org/pod/Mojo%3A%3ADOM58#find)). is '

    A

    B

    C

    ', dom { # Find all matching direct and indirect children find p => [ dom { text 'A' }, dom { text 'B' }, dom { text 'C' }, ]; }; ## tag tag CHECK Takes a check only. Extracts the tag of the current element (by calling ['tag' on the Mojo::DOM58 object](https://metacpan.org/pod/Mojo%3A%3ADOM58#tag)), and this is passed to the provided check. is '

    ', dom { tag 'p' }; ## text text CHECK Takes a check only. Extracts the text content from this element only (by calling ['text' on the Mojo::DOM58 object](https://metacpan.org/pod/Mojo%3A%3ADOM58#text)), and this is passed to the provided check. is '

    Hello, World!

    ', dom { text 'Hello, '; # OK: 'World!' is not in this element all_text 'Hello, World!'; # OK: use all_text for descendants' text }; ## val val CHECK _Available from version 0.004_. Takes a check only. Extracts the value from this element (by calling ['val' on the Mojo::DOM58 object](https://metacpan.org/pod/Mojo%3A%3ADOM58#val)), and this is passed to the provided check. is '', dom { val 42; attr value => 42; # The same, but longer }; # SEE ALSO - [Test2::Tools::HTTP](https://metacpan.org/pod/Test2%3A%3ATools%3A%3AHTTP) A perfect companion to this distribution: Test2::Tools::HTTP supports the requests, Test2::Tools::DOM can be used to check the responses. - [Test2::MojoX](https://metacpan.org/pod/Test2%3A%3AMojoX) If you are used to using Test::Mojo and are looking for a way to use it with the Test2 suite, then this distribution might be the right one for your needs. # COPYRIGHT AND LICENSE Copyright 2022 José Joaquín Atria This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.