Skip to content

$singleTextNode->is(':text') throws #49

Closed

Description

@rulatir

Guidelines

Description of the bug

Invoking ->is(':text') on a QueryPath object that contains a single text node throws.

This is the sixth PHP DOM library I'm trying this week, so with each new one I start by writing a couple of suitability tests. This is the first suitability test I wrote for querypath, and should serve as repro.

Expected: passing test

Actual:

Error: Call to undefined method DOMText::getElementsByTagName()
/home/rulatir/projects/cdatify/vendor/gravitypdf/querypath/src/CSS/DOMTraverser.php:595
/home/rulatir/projects/cdatify/vendor/gravitypdf/querypath/src/CSS/DOMTraverser.php:444
/home/rulatir/projects/cdatify/vendor/gravitypdf/querypath/src/CSS/DOMTraverser.php:144
/home/rulatir/projects/cdatify/vendor/gravitypdf/querypath/src/DOMQuery.php:161
/home/rulatir/projects/cdatify/vendor/gravitypdf/querypath/src/DOMQuery.php:1481
/home/rulatir/projects/cdatify/vendor/gravitypdf/querypath/src/Helpers/QueryChecks.php:66
/home/rulatir/projects/cdatify/tests/QueryPathSuitability.php:26

QueryPath version

3.2.3

PHP Version and environment (server type, cli provider etc., enclosing libraries and their respective versions)

8.3.4 (cli) on up-to-date Arch Linux

Minimal reproducible PHP+HTML snippet to replicate bug

<?php

use PHPUnit\Framework\TestCase;

class QueryPathSuitability extends TestCase
{
    public function testCheckingNodeType(): void
    {
        $q = html5qp('<processing-container>whatever</processing-container>');

        $container = $q->find('processing-container');
        self::assertEquals(1, $container->length);

        $contents = $container->contents();
        self::assertEquals(1, $contents->length);

        $firstItem = $contents->eq(0);
        self::assertEquals(1, $firstItem->length);

        // RELEVANT BIT STARTS HERE

        // nonidiomatic way works
        self::assertStringContainsString("Text", get_class($firstItem->toArray()[0]));

        // idiomatic way throws
        self::assertTrue($firstItem->is(':text'));
    }
}

Activity

  1. jakejackson1 commented on Mar 21, 2024

    @jakejackson1
    Member

    Hi @rulatir,

    Thanks for taking the time to report this. We certainly will want to fix the PHP error that's occurring when passing this pseudo-class selector to is().

    You should be aware that even when we do, your test self::assertTrue($firstItem->is(':text')); will fail. This library was originally created as the PHP equivalent of jQuery. In jQuery the custom pseudo-class selector :text only matches the <input> and <input type="text"/> tags. It won't tell you if $firstItem is a text node.

    Source: https://api.jquery.com/text-selector/

  2. rulatir commented on Mar 21, 2024

    @rulatir
    Author

    What is then the idiomatic way to determine whether the collection is holding a text node? $q->get(0) instanceof DOMText?

  3. jakejackson1 commented on Mar 21, 2024

    @jakejackson1
    Member

    @rulatir the QueryPath way would be $this->assertNotEmpty($firstItem->text());, which will return the contents of textContent for all matches in the current collection.

    But if you really need low-level access to the DOM classes in a collection, this can be done via ->toArray() or ->get(). You can then check the class type or $item->nodeType (https://www.php.net/manual/en/dom.constants.php).

    I've incorporated your bug report into a draft pull request so the PHP error can be fixed in the future: #50. If you have further questions about using QueryPath please open a Discussion: https://github.com/GravityPDF/querypath/discussions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions