浏览代码

HasMany单测

jqh 5 年之前
父节点
当前提交
9a4f9f9e0e

+ 13 - 13
tests/Browser/AuthTest.php

@@ -18,7 +18,7 @@ class AuthTest extends TestCase
     {
         $this->browse(function (Browser $browser) {
             $browser->visit(test_admin_path('auth/login'))
-                ->assertSee(__('admin.login'));
+                ->assertSeeText(__('admin.login'));
         });
     }
 
@@ -38,25 +38,25 @@ class AuthTest extends TestCase
 
             $browser->visit(test_admin_path('auth/login'))
                 ->assertPathIs(test_admin_path('auth/login'))
-                ->assertSee(__('admin.login'))
+                ->assertSeeText(__('admin.login'))
                 ->type('username', $credentials['username'])
                 ->type('password', $credentials['password'])
                 ->press(__('admin.login'))
                 ->waitForLocation(test_admin_path('/'), 3)
                 ->assertPathIs(test_admin_path('/'))
-                ->assertSee('Administrator')
-                ->assertSee('Dashboard')
-                ->assertSee('Description...')
-                ->assertSee('New Users')
-                ->assertSee('New Devices')
-                ->assertSee('Tickets')
-                ->assertSee(strtoupper(__('admin.documentation')))
-                ->assertSee(strtoupper(__('admin.extensions')))
-                ->assertSee(strtoupper(__('admin.demo')))
-                ->assertSee('GITHUB');
+                ->assertSeeText('Administrator')
+                ->assertSeeText('Dashboard')
+                ->assertSeeText('Description...')
+                ->assertSeeText('New Users')
+                ->assertSeeText('New Devices')
+                ->assertSeeText('Tickets')
+                ->assertSeeText((__('admin.documentation')))
+                ->assertSeeText((__('admin.extensions')))
+                ->assertSeeText((__('admin.demo')))
+                ->assertSeeText('GITHUB');
 
             $browser->within('.main-menu-content', function (Browser $browser) {
-                $browser->assertSee('Admin')
+                $browser->assertSeeText('Admin')
                     ->clickLink('Admin')
                     ->waitForText('Users', 1)
                     ->waitForText('Roles', 1)

+ 173 - 0
tests/Browser/Components/Form/Field/HasMany.php

@@ -0,0 +1,173 @@
+<?php
+
+namespace Tests\Browser\Components\Form\Field;
+
+use Laravel\Dusk\Browser;
+use PHPUnit\Framework\Assert as PHPUnit;
+use Tests\Browser\Components\Component;
+
+class HasMany extends Component
+{
+    protected $relation;
+
+    public function __construct($relation = null)
+    {
+        $this->relation = $relation;
+    }
+
+    /**
+     * 获取组件的 root selector.
+     *
+     * @return string
+     */
+    public function selector()
+    {
+        return '@container';
+    }
+
+    /**
+     * 浏览器包含组件的断言
+     *
+     * @param  Browser  $browser
+     * @return void
+     */
+    public function assert(Browser $browser)
+    {
+        $browser->assertVisible('@container')
+            ->assertVisible('@add')
+            ->assertVisible('@forms');
+    }
+
+    /**
+     * 读取组件的元素快捷方式.
+     *
+     * @return array
+     */
+    public function elements()
+    {
+        return [
+            '@container' => '.has-many-'.$this->relation,
+            '@add' => '.add',
+            '@remove' => '.remove',
+            '@forms' => ".has-many-{$this->relation}-forms",
+            '@group' => ".has-many-{$this->relation}-forms .fields-group",
+        ];
+    }
+
+    /**
+     * 点击添加按钮.
+     *
+     * @param Browser $browser
+     *
+     * @return int
+     */
+    public function add(Browser $browser)
+    {
+        $browser->script(
+            <<<JS
+$('{$this->formatSelector($browser, '@add')}').click();
+JS
+        );
+
+        // 获取最后一个添加的表单组
+        $index = $this->getLastFormGroupIndex($browser);
+
+        // 验证表单组是否存在
+        $this->withFormGroup($browser, $index);
+
+        return $index;
+    }
+
+    /**
+     * 获取最后一组新增的表单索引.
+     * 
+     * @param Browser $browser
+     * 
+     * @return int|null
+     */
+    public function getLastFormGroupIndex(Browser $browser)
+    {
+        // 获取添加的表单个数
+        $length = $browser->script(
+            <<<JS
+return $('{$this->formatSelector($browser, '@group')}').length;
+JS
+        );
+
+        return $length[0] ?? null;
+    }
+
+    /**
+     * @param Browser $browser
+     * @param \Closure $callback
+     *
+     * @return Browser
+     */
+    public function withLastFormGroup(Browser $browser, \Closure $callback = null)
+    {
+        return $this->withFormGroup($browser, $this->getLastFormGroupIndex($browser), $callback);
+    }
+
+    /**
+     * 检测表单组.
+     *
+     * @param Browser $browser
+     * @param \Closure $callback
+     * 
+     * @return Browser
+     */
+    public function withFormGroup(Browser $browser, $index, ?\Closure $callback = null)
+    {
+        // 添加的表单组容器选择器
+        $groupSelector = $this->formatGroupSelector($browser, $index);
+
+        $browser->assertVisible($groupSelector);
+        $browser->assertVisible("{$groupSelector} {$this->formatSelectorWithoutPrefix($browser, '@remove')}");
+
+        return $callback ? $browser->with($groupSelector, $callback) : $browser;
+    }
+
+    /**
+     * @param Browser $browser
+     * @param int $index
+     *
+     * @return string
+     */
+    protected function formatGroupSelector(Browser $browser, $index)
+    {
+        return "{$this->formatSelectorWithoutPrefix($browser, '@group')}:nth-of-type({$index})";
+    }
+
+    /**
+     * 移除表单.
+     *
+     * @param Browser $browser
+     * @param int $index
+     *
+     * @return Browser
+     */
+    public function remove(Browser $browser, $index)
+    {
+        $this->withFormGroup($browser, $index, function (Browser $browser) {
+            $browser->script(
+                <<<JS
+$('{$this->formatSelector($browser, $this->elements()['@remove'])}').click();
+JS
+            );
+        });
+
+        return $browser->assertHidden($this->formatGroupSelector($browser, $index));
+    }
+
+    /**
+     * 移除最后一个表单.
+     *
+     * @param Browser $browser
+     *
+     * @return Browser
+     */
+    public function removeLast(Browser $browser)
+    {
+        return $this->remove($browser, $this->getLastFormGroupIndex($browser));
+    }
+}

+ 10 - 10
tests/Browser/Components/Form/MenuCreationForm.php

@@ -35,18 +35,18 @@ class MenuCreationForm extends Component
      */
     public function assert(Browser $browser)
     {
-        $browser->assertSee(__('admin.submit'))
-            ->assertSee(__('admin.reset'))
+        $browser->assertSeeText(__('admin.submit'))
+            ->assertSeeText(__('admin.reset'))
             ->within('@form', function (Browser $browser) {
                 $browser
-                    ->assertSee(__('admin.parent_id'))
-                    ->assertSee(__('admin.title'))
-                    ->assertSee(__('admin.icon'))
-                    ->assertSee(__('admin.uri'))
-                    ->assertSee(__('admin.roles'))
-                    ->assertSee(__('admin.permission'))
-                    ->assertSee(__('admin.selectall'))
-                    ->assertSee(__('admin.expand'))
+                    ->assertSeeText(__('admin.parent_id'))
+                    ->assertSeeText(__('admin.title'))
+                    ->assertSeeText(__('admin.icon'))
+                    ->assertSeeText(__('admin.uri'))
+                    ->assertSeeText(__('admin.roles'))
+                    ->assertSeeText(__('admin.permission'))
+                    ->assertSeeText(__('admin.selectall'))
+                    ->assertSeeText(__('admin.expand'))
                     ->hasInput('title')
                     ->hasInput('icon')
                     ->hasInput('uri')

+ 13 - 13
tests/Browser/Components/Form/MenuEditForm.php

@@ -32,21 +32,21 @@ class MenuEditForm extends MenuCreationForm
      */
     public function assert(Browser $browser)
     {
-        $browser->assertSee(__('admin.submit'))
-            ->assertSee(__('admin.reset'))
+        $browser->assertSeeText(__('admin.submit'))
+            ->assertSeeText(__('admin.reset'))
             ->within('@form', function (Browser $browser) {
                 $browser
-                    ->assertSee('ID')
-                    ->assertSee(__('admin.parent_id'))
-                    ->assertSee(__('admin.title'))
-                    ->assertSee(__('admin.icon'))
-                    ->assertSee(__('admin.uri'))
-                    ->assertSee(__('admin.roles'))
-                    ->assertSee(__('admin.permission'))
-                    ->assertSee(__('admin.created_at'))
-                    ->assertSee(__('admin.updated_at'))
-                    ->assertSee(__('admin.selectall'))
-                    ->assertSee(__('admin.expand'))
+                    ->assertSeeText('ID')
+                    ->assertSeeText(__('admin.parent_id'))
+                    ->assertSeeText(__('admin.title'))
+                    ->assertSeeText(__('admin.icon'))
+                    ->assertSeeText(__('admin.uri'))
+                    ->assertSeeText(__('admin.roles'))
+                    ->assertSeeText(__('admin.permission'))
+                    ->assertSeeText(__('admin.created_at'))
+                    ->assertSeeText(__('admin.updated_at'))
+                    ->assertSeeText(__('admin.selectall'))
+                    ->assertSeeText(__('admin.expand'))
                     ->hasInput('title')
                     ->hasInput('icon')
                     ->hasInput('uri')

+ 11 - 1
tests/Browser/HasManyTest.php

@@ -3,6 +3,7 @@
 namespace Tests\Browser;
 
 use Laravel\Dusk\Browser;
+use Tests\Browser\Components\Form\Field\HasMany;
 use Tests\TestCase;
 
 /**
@@ -16,7 +17,16 @@ class HasManyTest extends TestCase
     {
         $this->browse(function (Browser $browser) {
             $browser->visit(test_admin_path('tests/painters/create'))
-                ->assertPathIs(test_admin_path('tests/painters/create'));
+                ->assertPathIs(test_admin_path('tests/painters/create'))
+                ->with('form[method="POST"]', function (Browser $browser) {
+                    $browser->assertSeeText('Paintings')
+                        ->with(new HasMany('paintings'), function (Browser $browser) {
+                            // 点击新增
+                            $browser->add();
+                            // 点击删除
+                            $browser->removeLast();
+                        });
+                });
         });
     }
 }

+ 10 - 10
tests/Browser/IndexTest.php

@@ -16,16 +16,16 @@ class IndexTest extends TestCase
     {
         $this->browse(function (Browser $browser) {
             $browser->visit(test_admin_path('/'))
-                ->assertSee('Administrator')
-                ->assertSee('Dashboard')
-                ->assertSee('Description...')
-                ->assertSee('New Users')
-                ->assertSee('New Devices')
-                ->assertSee('Tickets')
-                ->assertSee(strtoupper(__('admin.documentation')))
-                ->assertSee(strtoupper(__('admin.extensions')))
-                ->assertSee(strtoupper(__('admin.demo')))
-                ->assertSee('GITHUB');
+                ->assertSeeText('Administrator')
+                ->assertSeeText('Dashboard')
+                ->assertSeeText('Description...')
+                ->assertSeeText('New Users')
+                ->assertSeeText('New Devices')
+                ->assertSeeText('Tickets')
+                ->assertSeeText(__('admin.documentation'))
+                ->assertSeeText(__('admin.extensions'))
+                ->assertSeeText(__('admin.demo'))
+                ->assertSeeText('GITHUB');
         });
     }
 

+ 1 - 1
tests/Browser/MenuTest.php

@@ -109,7 +109,7 @@ class MenuTest extends TestCase
                         // 检测表单
                         $browser->fill($updates);
                     }, 3)
-                        ->assertSee(__('admin.edit'))
+                        ->assertSeeText(__('admin.edit'))
                         ->click('div')
                         ->whenElementAvailable(new MultipleSelect2('select[name="roles[]"]'), function (Browser $browser) {
                             $browser->choose(1);

+ 13 - 13
tests/Browser/OperationLogTest.php

@@ -23,20 +23,20 @@ class OperationLogTest extends TestCase
             $browser->visit(test_admin_path('auth/menu'))
                 ->assertPathIs(test_admin_path('auth/menu'))
                 ->visit(test_admin_path('auth/logs'))
-                ->assertSee(__('admin.operation_log'))
-                ->assertSee(__('admin.list'))
-                ->assertSee(__('admin.refresh'))
-                ->assertSee(__('admin.filter'))
-                ->assertSee('ID')
-                ->assertSee(strtoupper(__('admin.user')))
-                ->assertSee(strtoupper(__('admin.method')))
-                ->assertSee(strtoupper(__('admin.uri')))
-                ->assertSee('IP')
-                ->assertSee(strtoupper(__('admin.input')))
-                ->assertSee(strtoupper(__('admin.created_at')))
-                ->assertSee(strtoupper(__('admin.action')))
+                ->assertSeeText(__('admin.operation_log'))
+                ->assertSeeText(__('admin.list'))
+                ->assertSeeText(__('admin.refresh'))
+                ->assertSeeText(__('admin.filter'))
+                ->assertSeeText('ID')
+                ->assertSeeText((__('admin.user')))
+                ->assertSeeText((__('admin.method')))
+                ->assertSeeText((__('admin.uri')))
+                ->assertSeeText('IP')
+                ->assertSeeText((__('admin.input')))
+                ->assertSeeText((__('admin.created_at')))
+                ->assertSeeText((__('admin.action')))
                 ->waitForText(__('admin.responsive.display'), 2)
-                ->assertSee(__('admin.responsive.display_all'));
+                ->assertSeeText(__('admin.responsive.display_all'));
         });
     }
 

+ 6 - 6
tests/Browser/Pages/MenuEditPage.php

@@ -32,12 +32,12 @@ class MenuEditPage extends Page
      */
     public function assert(Browser $browser)
     {
-        $browser->assertSee(__('admin.menu'))
-            ->assertSee(__('admin.edit'))
-            ->assertSee(__('admin.list'))
-            ->assertSee(__('admin.delete'))
-            ->assertSee(__('admin.submit'))
-            ->assertSee(__('admin.reset'))
+        $browser->assertSeeText(__('admin.menu'))
+            ->assertSeeText(__('admin.edit'))
+            ->assertSeeText(__('admin.list'))
+            ->assertSeeText(__('admin.delete'))
+            ->assertSeeText(__('admin.submit'))
+            ->assertSeeText(__('admin.reset'))
             ->assert(new MenuEditForm($this->id));
     }
 

+ 20 - 20
tests/Browser/Pages/MenuPage.php

@@ -25,29 +25,29 @@ class MenuPage extends Page
      */
     public function assert(Browser $browser)
     {
-        $browser->assertSee(__('admin.expand'))
-            ->assertSee(__('admin.collapse'))
-            ->assertSee(__('admin.save'))
-            ->assertSee(__('admin.new'))
+        $browser->assertSeeText(__('admin.expand'))
+            ->assertSeeText(__('admin.collapse'))
+            ->assertSeeText(__('admin.save'))
+            ->assertSeeText(__('admin.new'))
             ->whenAvailable('@tree', function (Browser $browser) {
-                $browser->assertSee('Menu')
-                    ->assertSee('Index')
-                    ->assertSee('Admin')
-                    ->assertSee('Users')
-                    ->assertSee('Roles')
-                    ->assertSee('Permission')
-                    ->assertSee('Menu')
-                    ->assertSee('Operation log');
+                $browser->assertSeeText('Menu')
+                    ->assertSeeText('Index')
+                    ->assertSeeText('Admin')
+                    ->assertSeeText('Users')
+                    ->assertSeeText('Roles')
+                    ->assertSeeText('Permission')
+                    ->assertSeeText('Menu')
+                    ->assertSeeText('Operation log');
             }, 1)
             ->within('@form', function (Browser $browser) {
-                $browser->assertSee(__('admin.parent_id'))
-                    ->assertSee(__('admin.title'))
-                    ->assertSee(__('admin.icon'))
-                    ->assertSee(__('admin.uri'))
-                    ->assertSee(__('admin.roles'))
-                    ->assertSee(__('admin.permission'))
-                    ->assertSee(__('admin.selectall'))
-                    ->assertSee(__('admin.expand'))
+                $browser->assertSeeText(__('admin.parent_id'))
+                    ->assertSeeText(__('admin.title'))
+                    ->assertSeeText(__('admin.icon'))
+                    ->assertSeeText(__('admin.uri'))
+                    ->assertSeeText(__('admin.roles'))
+                    ->assertSeeText(__('admin.permission'))
+                    ->assertSeeText(__('admin.selectall'))
+                    ->assertSeeText(__('admin.expand'))
                     ->assertSelected('parent_id', 0)
                     ->hasInput('title')
                     ->hasInput('icon')

+ 32 - 16
tests/BrowserExtension.php

@@ -14,6 +14,7 @@ trait BrowserExtension
     public function extendBrowser()
     {
         $functions = [
+            // 等待文本可见
             'whenTextAvailable' => function ($text, $callbackOrSeconds = null, $seconds = null) {
                 $callback = null;
 
@@ -36,7 +37,7 @@ trait BrowserExtension
                     return $results;
                 }, $message);
             },
-
+            // 等待元素可见
             'whenElementAvailable' => function ($selector, $callbackOrSeconds = null, $seconds = null) {
                 $callback = null;
                 if (is_callable($callbackOrSeconds)) {
@@ -49,38 +50,53 @@ trait BrowserExtension
                     $callback && $callback($value);
                 }, $seconds);
             },
-
+            // 判断input框是否存在
             'hasInput' => function ($field) {
                 /* @var \Facebook\WebDriver\Remote\RemoteWebElement $element */
                 $this->resolver->resolveForTyping($field);
 
                 return $this;
             },
+            // 判断元素是否不可见
+            'assertHidden' => function ($selector) {
+                $fullSelector = $this->resolver->format($selector);
 
-            'wait' => function ($seconds, \Closure $callback = null) {
-                try {
-                    $this->waitUsing($seconds, 200, function () {
-                    });
-                } catch (TimeoutException $e) {
-                    $callback && $callback();
-                }
+                $isHidden = $this->script(
+                    <<<JS
+var display = $('{$fullSelector}').css('display');                    
+                    
+return display === 'none' || $('{$fullSelector}').is(':hidden');
+JS
+                );
+
+                PHPUnit::assertTrue(
+                    (bool) ($isHidden[0] ?? false),
+                    "Element [{$fullSelector}] is displayed."
+                );
 
                 return $this;
             },
-
-            'assertHidden' => function ($selector) {
+            // 判断是否是给定组件
+            'is' => function (Component $component) {
+                return $this->with($component, function () {
+                });
+            },
+            // 判断文本是否存在,忽略大小写
+            'assertSeeTextIn' => function (?string $selector, ?string $text) {
                 $fullSelector = $this->resolver->format($selector);
 
+                $element = $this->resolver->findOrFail($selector);
+
                 PHPUnit::assertTrue(
-                    $this->resolver->findOrFail($selector)->isDisplayed(),
-                    "Element [{$fullSelector}] is visible."
+                    Str::contains(strtolower($element->getText()), strtolower($text)),
+                    "Did not see expected text [{$text}] within element [{$fullSelector}]."
                 );
 
                 return $this;
             },
-            'assert' => function (Component $component) {
-                return $this->with($component, function () {
-                });
+            // 判断文本是否存在,忽略大小写
+            'assertSeeText' => function (?string $text) {
+                return $this->assertSeeTextIn('', $text);
             },
         ];
 

+ 1 - 1
tests/Models/Painter.php

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
 
 class Painter extends Model
 {
-    protected $table = 'demo_painters';
+    protected $table = 'test_painters';
 
     public function paintings()
     {

+ 1 - 1
tests/Models/Painting.php

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
 
 class Painting extends Model
 {
-    protected $table = 'demo_paintings';
+    protected $table = 'test_paintings';
 
     protected $fillable = ['title', 'body', 'completed_at'];
 

+ 3 - 2
tests/resources/.ide-helper.php

@@ -8,9 +8,10 @@ namespace Laravel\Dusk
      * @method $this whenTextAvailable(string $text, $callbackOrSeconds = null, int $seconds = null)
      * @method $this whenElementAvailable($selector, $callbackOrSeconds = null, int $seconds = null)
      * @method $this hasInput($field)
-     * @method $this wait(int $seconds, $callback = null)
      * @method $this assertHidden($selector)
-     * @method $this assert(Component $component)
+     * @method $this is(Component $component)
+     * @method $this assertSeeTextIn(string $selector, string $text)
+     * @method $this assertSeeText(string $text)
      */
     class Browser
     {