【问题标题】:Laravel test order of elements on pageLaravel 测试页面上元素的顺序
【发布时间】:2017-03-24 12:12:11
【问题描述】:

我想用 Laravel TestCase 测试我的排序是否正常工作。我有简单的测试页面:

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

现在我想测试第一个 .test-class 元素是否包含 'Value1'。我尝试了不同的方法,但没有成功。这是第一个:

 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');

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

然后我尝试了

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

也变绿了。所以这种方法也行不通。

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

【问题讨论】:

    标签: php css laravel testing selector


    【解决方案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】:

      不是针对您的特定问题的解决方案,而是针对您的问题的解决方法: 您可以使用包含当前循环迭代次数的 $loop-&gt;iteration 辅助变量枚举您的 test-class 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');
      

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

          所以,我已经解决了。关键是查看 \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');
          

          【讨论】:

            猜你喜欢
            • 2011-05-04
            • 2023-04-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-07-16
            • 1970-01-01
            相关资源
            最近更新 更多