Laravel页面上元素的测试顺序

时间:2017-03-24 12:12:11

标签: php css laravel testing selector

我想测试我的排序是否与Laravel TestCase一起正常运行。我有简单的测试页面:

<div id="values">
    @foreach(['Value1', 'Value2'] as $value)
        <div class="test-class">{{$value}}</div>
    @endforeach
</div>

现在我想测试第一个 .test-class 元素是否包含&#39; Value1&#39; 。我曾尝试过不同的方法,并没有成功。这是第一个:

 public function testSorting()
{
    $this->visit(route('dummy'));
    $this->see('Value1');
    $this->seeInElement('.test-class:first-of-type', 'Value2');
}

这个导致例外:

Symfony\Component\CssSelector\Exception\ExpressionErrorException: "*:first-of-type" is not implemented.

然后我试了

$this->seeInElement('#values:first-child', 'Value2');

我的测试是绿色的。但它应该是红色的,因为第一个孩子是&#39; Value1&#39; 。它完全忽略了&#39;:first-child&#39; 部分。

然后我试了

$this->seeInElement('#values:nth-child(1)', 'Value2');

也变绿了。所以这种方法也不起作用。

我错过了什么吗?或者没有办法用Laravel测试来测试页面上元素的顺序?

4 个答案:

答案 0 :(得分:1)

不是针对您的具体问题的解决方案,而是针对您的问题的解决方法: 您可以使用test-class辅助变量枚举$loop->iteration div,其中包含当前循环迭代的编号。

<div id="values">
    @foreach(['Value1', 'Value2'] as $value)
        <div class="test-class" id="value_{{$loop->iteration}}">{{$value}}</div>
    @endforeach
</div>

现在你的div类有一个以1开头的枚举id,你可以在测试中使用选择器#value_1来选择第一个div:

$this->seeInElement('#value_1', 'Value2');

答案 1 :(得分:1)

我在这里参加聚会迟到了,但是我一直在用下面的方法检查页面上项目的顺序。到目前为止看来工作得很好。

在您的TestCase基类上实现以下方法。

/**
 * Given a CSS selector string, check if the elements matching the query
 * contain the values provided, in the order they are provided.
 *
 * @param string $selector
 * @param array $contents
 * @return $this
 */
public function seeInOrder($selector, Array $contents)
{
    $matches = $this->crawler->filter($selector);

    try {
        foreach ($matches as $index => $domElement) {
            $needle = $contents[$index];
            $this->assertContains($needle, trim($domElement->textContent));
        }
    } catch (PHPUnit_Framework_ExpectationFailedException $e) {
        $this->fail('Failed asserting that the element at index ' . $index . ' contains the string "' . $contents[$index] . '"');
    }

    return $this;
}

用法:

/**
 * Test that the /books route returns a list of books in explicit order.
 *
 * @test
 * @return void
 */
public function books_index_page_lists_books_in_explicit_order()
{
    $book_1 = factory(App\Book::class)->create([
        'order' => 0
    ]);

    $book_2 = factory(App\Book::class)->create([
        'order' => 1
    ]);

    $this->visit('/books')
        ->see($book_1->title)
        ->see($book_2->title)
        ->seeInOrder('.books .book', [
            $book_1->title,
            $book_2->title
        ]);
}

答案 2 :(得分:0)

所以,我已经解决了。关键是要研究 \ Symfony \ Component \ DomCrawler \ Crawler 类。它有很多有用的方法,如 first() last() eq($ number)。我在 TestCase 类中创建了这个方法:

public function seeInFirstElement($selector, $text)
{
    $this->assertContains($text, trim($this->crawler->filter($selector)->first()->text()));

    return $this;
}

您可以摆脱 trim()功能,但是如果测试失败,输出看起来会更好。 所以,在我的测试中,我使用这样的结构来测试排序:

$this->seeInFirstElement('.test-class', 'Value1');

答案 3 :(得分:-1)

我在HTTP测试中偶然发现了这个问题,如果您使用它,则无需像下面的答案中那样构建自己的函数。 Laravel附带了一些断言,包括assertSeeInOrderhttps://laravel.com/docs/7.x/http-tests#assert-see-in-order