add nova
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class ActionDropdownComponent extends Component
|
||||
{
|
||||
/**
|
||||
* Get the root selector for the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
return 'div[data-menu-open="true"]';
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the action with the given URI key.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $uriKey
|
||||
* @return void
|
||||
*/
|
||||
public function runWithConfirmation(Browser $browser, string $uriKey)
|
||||
{
|
||||
$browser->click("button[data-action-id='{$uriKey}']")
|
||||
->elsewhereWhenAvailable(new Modals\ConfirmActionModalComponent(), function ($browser) {
|
||||
$browser->confirm();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the action with the given URI key.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $uriKey
|
||||
* @return void
|
||||
*/
|
||||
public function runWithoutConfirmation(Browser $browser, string $uriKey)
|
||||
{
|
||||
$browser->click("button[data-action-id='{$uriKey}']")
|
||||
->elsewhere('', function ($browser) {
|
||||
$browser->assertDontSee('@cancel-action-button');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the action modal but cancel the action.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $uriKey
|
||||
* @param callable $fieldCallback
|
||||
* @return void
|
||||
*/
|
||||
public function select(Browser $browser, string $uriKey, $fieldCallback)
|
||||
{
|
||||
$browser->click("button[data-action-id='{$uriKey}']")
|
||||
->elsewhereWhenAvailable(new Modals\ConfirmActionModalComponent(), function ($browser) use ($fieldCallback) {
|
||||
$fieldCallback($browser);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the action modal but cancel the action.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $uriKey
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(Browser $browser, string $uriKey)
|
||||
{
|
||||
$browser->click("button[data-action-id='{$uriKey}']")
|
||||
->elsewhereWhenAvailable(new Modals\ConfirmActionModalComponent(), function ($browser) {
|
||||
$browser->cancel();
|
||||
});
|
||||
}
|
||||
}
|
||||
42
nova/src/Testing/Browser/Components/BreadcrumbComponent.php
Normal file
42
nova/src/Testing/Browser/Components/BreadcrumbComponent.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class BreadcrumbComponent extends Component
|
||||
{
|
||||
/**
|
||||
* Get the root selector for the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
return 'nav[aria-label="breadcrumb"]';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert current page match the title.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $title
|
||||
* @return void
|
||||
*/
|
||||
public function assertCurrentPageTitle(Browser $browser, string $title)
|
||||
{
|
||||
$browser->assertSeeIn('@current-page', $title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'@current-page' => 'li[aria-current="page"]',
|
||||
];
|
||||
}
|
||||
}
|
||||
11
nova/src/Testing/Browser/Components/Component.php
Normal file
11
nova/src/Testing/Browser/Components/Component.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components;
|
||||
|
||||
use Laravel\Dusk\Component as BaseComponent;
|
||||
use Laravel\Nova\Testing\Browser\Concerns\InteractsWithElements;
|
||||
|
||||
abstract class Component extends BaseComponent
|
||||
{
|
||||
use InteractsWithElements;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components\Controls;
|
||||
|
||||
class RelationSelectControlComponent extends SelectControlComponent
|
||||
{
|
||||
/**
|
||||
* Get the root selector associated with this component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
return "@{$this->attribute}-select";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components\Controls;
|
||||
|
||||
use Laravel\Nova\Testing\Browser\Components\Component;
|
||||
|
||||
class SelectControlComponent extends Component
|
||||
{
|
||||
public $attribute;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(string $attribute)
|
||||
{
|
||||
$this->attribute = $attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root selector associated with this component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
return "select[dusk='{$this->attribute}']";
|
||||
}
|
||||
}
|
||||
75
nova/src/Testing/Browser/Components/DetailComponent.php
Executable file
75
nova/src/Testing/Browser/Components/DetailComponent.php
Executable file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class DetailComponent extends Component
|
||||
{
|
||||
public $resourceName;
|
||||
|
||||
public $resourceId;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param int $resourceId
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($resourceName, $resourceId)
|
||||
{
|
||||
$this->resourceName = $resourceName;
|
||||
$this->resourceId = $resourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the delete selector.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function openControlSelector(Browser $browser)
|
||||
{
|
||||
$browser->whenAvailable("@{$this->resourceId}-control-selector", function ($browser) {
|
||||
$browser->click('');
|
||||
})->pause(100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root selector for the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
return '@'.$this->resourceName.'-detail-component';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser page contains the component.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
tap($this->selector(), function ($selector) use ($browser) {
|
||||
$browser->pause(100)
|
||||
->waitFor($selector)
|
||||
->assertVisible($selector);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the component.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
69
nova/src/Testing/Browser/Components/FormComponent.php
Normal file
69
nova/src/Testing/Browser/Components/FormComponent.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Nova\Testing\Browser\Concerns\InteractsWithInlineCreateRelation;
|
||||
|
||||
class FormComponent extends Component
|
||||
{
|
||||
use InteractsWithInlineCreateRelation;
|
||||
|
||||
protected $selector;
|
||||
|
||||
protected $formUniqueId;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @param string|null $selector
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($selector = null)
|
||||
{
|
||||
$this->selector = $selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root selector for the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
return $this->selector ?? '#app [dusk="content"] form:not([dusk="form-button"])';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a field's value using JavaScript.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function setFieldValue(Browser $browser, $attribute, $value)
|
||||
{
|
||||
$browser->script("Nova.\$emit('{$this->formUniqueId}-{$attribute}-value', '{$value}')");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser page contains the component.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
tap($this->selector(), function ($selector) use ($browser) {
|
||||
$browser->pause(100)
|
||||
->waitFor($selector)
|
||||
->assertVisible($selector)
|
||||
->scrollIntoView($selector);
|
||||
|
||||
$this->formUniqueId = $browser->attribute($selector, 'data-form-unique-id');
|
||||
});
|
||||
}
|
||||
}
|
||||
57
nova/src/Testing/Browser/Components/HeaderComponent.php
Normal file
57
nova/src/Testing/Browser/Components/HeaderComponent.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class HeaderComponent extends Component
|
||||
{
|
||||
/**
|
||||
* Get the root selector for the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
return 'div#app header';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser page contains the component.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
tap($this->selector(), function ($selector) use ($browser) {
|
||||
$browser->scrollIntoView($selector);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open notification panel.
|
||||
*
|
||||
* @param callable|null $notificationCallback
|
||||
* @return void
|
||||
*/
|
||||
public function showNotificationPanel(Browser $browser, $notificationCallback = null)
|
||||
{
|
||||
$browser
|
||||
->click('@notifications-dropdown')
|
||||
->elsewhereWhenAvailable('@notifications-content', $notificationCallback ?? function ($browser) {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the component.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
744
nova/src/Testing/Browser/Components/IndexComponent.php
Executable file
744
nova/src/Testing/Browser/Components/IndexComponent.php
Executable file
@@ -0,0 +1,744 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class IndexComponent extends Component
|
||||
{
|
||||
public $resourceName;
|
||||
|
||||
public $viaRelationship;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param string|null $viaRelationship
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($resourceName, $viaRelationship = null)
|
||||
{
|
||||
$this->resourceName = $resourceName;
|
||||
|
||||
if (! is_null($viaRelationship) && $resourceName !== $viaRelationship) {
|
||||
$this->viaRelationship = $viaRelationship;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root selector for the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
$selector = '[dusk="'.$this->resourceName.'-index-component"]';
|
||||
|
||||
return sprintf(
|
||||
! is_null($this->viaRelationship) ? '%s[data-relationship="%s"]' : '%s', $selector, $this->viaRelationship
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for table to be ready.
|
||||
*
|
||||
* @param int|null $seconds
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitForTable(Browser $browser, $seconds = null)
|
||||
{
|
||||
$browser->waitUntilMissing('@loading-view')
|
||||
->whenAvailable('@resource-table', function ($browser) use ($seconds) {
|
||||
$browser->waitFor('tbody', $seconds);
|
||||
}, $seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for empty dialog to be ready.
|
||||
*
|
||||
* @param int|null $seconds
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitForEmptyDialog(Browser $browser, $seconds = null)
|
||||
{
|
||||
$browser->waitUntilMissing('@loading-view')
|
||||
->waitFor('div[dusk="'.$this->resourceName.'-empty-dialog"]', $seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the given string.
|
||||
*
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function searchFor(Browser $browser, $search)
|
||||
{
|
||||
$browser->type('@search-input', $search)->pause(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the search field.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clearSearch(Browser $browser)
|
||||
{
|
||||
$browser->clear('@search-input')->type('@search-input', ' ')->pause(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the sortable icon for the given attribute.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return void
|
||||
*/
|
||||
public function sortBy(Browser $browser, $attribute)
|
||||
{
|
||||
$browser->click("@sort-{$attribute}")->waitForTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Paginate to the next page of resources.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function nextPage(Browser $browser)
|
||||
{
|
||||
$browser->click('@next')->waitForTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Paginate to the previous page of resources.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function previousPage(Browser $browser)
|
||||
{
|
||||
$browser->click('@previous')->waitForTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Select all the the resources on current page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function selectAllOnCurrentPage(Browser $browser)
|
||||
{
|
||||
$browser->within(new SelectAllDropdownComponent(), function (Browser $browser) {
|
||||
$browser->selectAllOnCurrentPage();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Un-select all the the resources on current page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unselectAllOnCurrentPage(Browser $browser)
|
||||
{
|
||||
$browser->within(new SelectAllDropdownComponent(), function ($browser) {
|
||||
$browser->unselectAllOnCurrentPage();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Select all the matching resources.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function selectAllMatching(Browser $browser)
|
||||
{
|
||||
$browser->within(new SelectAllDropdownComponent(), function ($browser) {
|
||||
$browser->selectAllMatching();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Un-select all the matching resources.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unselectAllMatching(Browser $browser)
|
||||
{
|
||||
$browser->within(new SelectAllDropdownComponent(), function ($browser) {
|
||||
$browser->unselectAllMatching();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on the matching total matching count text.
|
||||
*
|
||||
* @param int $count
|
||||
* @return void
|
||||
*/
|
||||
public function assertSelectAllMatchingCount(Browser $browser, $count)
|
||||
{
|
||||
$browser->within(new SelectAllDropdownComponent(), function ($browser) use ($count) {
|
||||
$browser->assertSelectAllMatchingCount($count);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given filter and filter value for the index.
|
||||
*
|
||||
* @param callable|null $fieldCallback
|
||||
* @param callable|bool|null $postCallback
|
||||
* @return void
|
||||
*/
|
||||
public function runFilter(Browser $browser, $fieldCallback = null, $postCallback = null)
|
||||
{
|
||||
$browser->openFilterSelector();
|
||||
|
||||
if (is_callable($fieldCallback)) {
|
||||
$browser->elsewhereWhenAvailable('@filter-menu', function (Browser $browser) use ($fieldCallback) {
|
||||
$fieldCallback($browser);
|
||||
});
|
||||
}
|
||||
|
||||
if ($postCallback !== false) {
|
||||
call_user_func($postCallback ?? function ($browser) {
|
||||
$browser->closeCurrentDropdown();
|
||||
}, $browser);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset current filter value for the index.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetFilter(Browser $browser)
|
||||
{
|
||||
$this->runFilter($browser, function ($browser) {
|
||||
$browser->press(Str::upper(__('Reset Filters')));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert current filter count for the index.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertFilterCount(Browser $browser, int $count)
|
||||
{
|
||||
$browser->within('@filter-selector-button', function ($browser) use ($count) {
|
||||
if ($count <= 0) {
|
||||
$browser->assertDontSee($count);
|
||||
} else {
|
||||
$browser->assertSee($count);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the per page value for the index.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPerPage(Browser $browser, $value)
|
||||
{
|
||||
$this->runFilter($browser, function ($browser) use ($value) {
|
||||
$browser->whenAvailable('select[dusk="per-page-select"]', function ($browser) use ($value) {
|
||||
$browser->select('', $value);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given filter and filter value for the index.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @return void
|
||||
*/
|
||||
public function selectFilter(Browser $browser, $name, $value)
|
||||
{
|
||||
$this->runFilter($browser, function ($browser) use ($name, $value) {
|
||||
$browser->whenAvailable('select[dusk="'.$name.'-select-filter"]', function ($browser) use ($value) {
|
||||
$browser->select('', $value)->pause(1000);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that trashed records should not be displayed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withoutTrashed(Browser $browser)
|
||||
{
|
||||
$this->runFilter($browser, function ($browser) {
|
||||
$browser->whenAvailable('[dusk="filter-soft-deletes"]', function ($browser) {
|
||||
$browser->select('select[dusk="trashed-select"]', '')->pause(1000);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that only trashed records should be displayed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onlyTrashed(Browser $browser)
|
||||
{
|
||||
$this->runFilter($browser, function ($browser) {
|
||||
$browser->whenAvailable('[dusk="filter-soft-deletes"]', function ($browser) {
|
||||
$browser->select('select[dusk="trashed-select"]', 'only')->pause(1000);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that trashed records should be displayed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withTrashed(Browser $browser)
|
||||
{
|
||||
$this->runFilter($browser, function ($browser) {
|
||||
$browser->whenAvailable('[dusk="filter-soft-deletes"]', function ($browser) {
|
||||
$browser->select('select[dusk="trashed-select"]', 'with');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the action selector.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function openActionSelector(Browser $browser)
|
||||
{
|
||||
$browser->whenAvailable('@action-select', function ($browser) {
|
||||
$browser->click('')->pause(100);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the standalone action selector.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function openStandaloneActionSelector(Browser $browser)
|
||||
{
|
||||
$browser->whenAvailable('@index-standalone-action-dropdown', function ($browser) {
|
||||
$browser->click('')->pause(100);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the filter selector.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function openFilterSelector(Browser $browser)
|
||||
{
|
||||
$browser->whenAvailable('@filter-selector', function ($browser) {
|
||||
$browser->click('')->pause(100);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the action selector.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function openControlSelectorById(Browser $browser, $id)
|
||||
{
|
||||
$browser
|
||||
->whenAvailable("@{$id}-control-selector", function ($browser) {
|
||||
$browser->click('')->pause(300);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* assert the action selector is present by ID.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return void
|
||||
*/
|
||||
public function assertPresentControlSelectorById(Browser $browser, $id)
|
||||
{
|
||||
$browser->assertPresent("@{$id}-control-selector");
|
||||
}
|
||||
|
||||
/**
|
||||
* assert the action selector is missing by ID.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return void
|
||||
*/
|
||||
public function assertMissingControlSelectorById(Browser $browser, $id)
|
||||
{
|
||||
$browser->assertMissing("@{$id}-control-selector");
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the action with the given URI key.
|
||||
*
|
||||
* @param string $uriKey
|
||||
* @param callable $fieldCallback
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function selectAction(Browser $browser, $uriKey, $fieldCallback)
|
||||
{
|
||||
$browser->whenAvailable('select[dusk="action-select"]', function ($browser) use ($uriKey) {
|
||||
$browser->select('', $uriKey)
|
||||
->pause(100)
|
||||
->assertSelected('', '');
|
||||
});
|
||||
|
||||
$browser->elsewhereWhenAvailable(new Modals\ConfirmActionModalComponent(), function ($browser) use ($fieldCallback) {
|
||||
$fieldCallback($browser);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the standalone action with the given URI key.
|
||||
*
|
||||
* @param string $uriKey
|
||||
* @param callable $fieldCallback
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function selectStandaloneAction(Browser $browser, $uriKey, $fieldCallback)
|
||||
{
|
||||
$browser->whenAvailable('@index-standalone-action-dropdown', function ($browser) {
|
||||
$browser->click('');
|
||||
})->elseWhereWhenAvailable('div[data-menu-open="true"]', function ($browser) use ($uriKey) {
|
||||
$browser->click("button[data-action-id='{$uriKey}']");
|
||||
});
|
||||
|
||||
$browser->elsewhereWhenAvailable(new Modals\ConfirmActionModalComponent(), function ($browser) use ($fieldCallback) {
|
||||
$fieldCallback($browser);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the action with the given URI key.
|
||||
*
|
||||
* @param string $uriKey
|
||||
* @param callable|null $fieldCallback
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function runAction(Browser $browser, $uriKey, $fieldCallback = null)
|
||||
{
|
||||
$this->selectAction($browser, $uriKey, function ($browser) use ($fieldCallback) {
|
||||
if ($fieldCallback) {
|
||||
$fieldCallback($browser);
|
||||
}
|
||||
|
||||
$browser->waitForText('Run Action')->click('@confirm-action-button')->pause(250);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the standalone action with the given URI key.
|
||||
*
|
||||
* @param string $uriKey
|
||||
* @param callable|null $fieldCallback
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function runStandaloneAction(Browser $browser, $uriKey, $fieldCallback = null)
|
||||
{
|
||||
$this->selectStandaloneAction($browser, $uriKey, function ($browser) use ($fieldCallback) {
|
||||
$browser->pause(2000);
|
||||
|
||||
if ($fieldCallback) {
|
||||
$fieldCallback($browser);
|
||||
}
|
||||
|
||||
$browser->waitForText('Run Action')->click('@confirm-action-button')->pause(250);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the action with the given URI key.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @param string $uriKey
|
||||
* @param callable $fieldCallback
|
||||
* @return void
|
||||
*/
|
||||
public function selectInlineAction(Browser $browser, $id, $uriKey, $fieldCallback)
|
||||
{
|
||||
$browser->openControlSelectorById($id)
|
||||
->elseWhereWhenAvailable('div[data-menu-open="true"]', function ($browser) use ($uriKey) {
|
||||
$browser->click("button[data-action-id='{$uriKey}']");
|
||||
})->pause(500);
|
||||
|
||||
$browser->elsewhereWhenAvailable(new Modals\ConfirmActionModalComponent(), function ($browser) use ($fieldCallback) {
|
||||
$fieldCallback($browser);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the action with the given URI key.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @param string $uriKey
|
||||
* @param callable|null $fieldCallback
|
||||
* @return void
|
||||
*/
|
||||
public function runInlineAction(Browser $browser, $id, $uriKey, $fieldCallback = null)
|
||||
{
|
||||
$this->selectInlineAction($browser, $id, $uriKey, function ($browser) use ($fieldCallback) {
|
||||
if ($fieldCallback) {
|
||||
$fieldCallback($browser);
|
||||
}
|
||||
|
||||
$browser->click('@confirm-action-button')->pause(250);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the user at the given resource table row index.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @param int|string|null $pivotId
|
||||
* @return void
|
||||
*/
|
||||
public function clickCheckboxForId(Browser $browser, $id, $pivotId = null)
|
||||
{
|
||||
if (! is_null($pivotId)) {
|
||||
$browser->click('[data-pivot-id="'.$pivotId.'"][dusk="'.$id.'-row"] [role="checkbox"]');
|
||||
} else {
|
||||
$browser->click('[dusk="'.$id.'-checkbox"]');
|
||||
}
|
||||
|
||||
$browser->pause(175);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replicate the given resource table row index.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return void
|
||||
*/
|
||||
public function replicateResourceById(Browser $browser, $id)
|
||||
{
|
||||
$browser->openControlSelectorById($id)
|
||||
->elsewhereWhenAvailable("@{$id}-replicate-button", function ($browser) {
|
||||
$browser->click('');
|
||||
})->pause(500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Preview the given resource table row index.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return void
|
||||
*/
|
||||
public function previewResourceById(Browser $browser, $id)
|
||||
{
|
||||
$browser->openControlSelectorById($id)
|
||||
->elsewhereWhenAvailable("@{$id}-preview-button", function ($browser) {
|
||||
$browser->click('');
|
||||
})->pause(500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the user at the given resource table row index.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return void
|
||||
*/
|
||||
public function deleteResourceById(Browser $browser, $id)
|
||||
{
|
||||
$browser->click("@{$id}-delete-button")
|
||||
->elsewhereWhenAvailable(new Modals\DeleteResourceModalComponent(), function ($browser) {
|
||||
$browser->confirm();
|
||||
})->pause(500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the user at the given resource table row index.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return void
|
||||
*/
|
||||
public function restoreResourceById(Browser $browser, $id)
|
||||
{
|
||||
$browser->click("@{$id}-restore-button")
|
||||
->elsewhereWhenAvailable(new Modals\RestoreResourceModalComponent(), function ($browser) {
|
||||
$browser->confirm();
|
||||
})->pause(500);
|
||||
}
|
||||
|
||||
/**
|
||||
* View the user at the given resource table row index.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return void
|
||||
*/
|
||||
public function viewResourceById(Browser $browser, $id)
|
||||
{
|
||||
$browser->click("@{$id}-view-button")->pause(500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit the user at the given resource table row index.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return void
|
||||
*/
|
||||
public function editResourceById(Browser $browser, $id)
|
||||
{
|
||||
$browser->click("@{$id}-edit-button")->pause(500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the resources selected via checkboxes.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteSelected(Browser $browser)
|
||||
{
|
||||
$browser->click('@delete-menu')
|
||||
->pause(300)
|
||||
->elsewhere('', function ($browser) {
|
||||
$browser->click('[dusk="delete-selected-button"]')
|
||||
->elsewhereWhenAvailable(new Modals\DeleteResourceModalComponent(), function ($browser) {
|
||||
$browser->confirm();
|
||||
});
|
||||
})->pause(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the resources selected via checkboxes.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function restoreSelected(Browser $browser)
|
||||
{
|
||||
$browser->click('@delete-menu')
|
||||
->pause(300)
|
||||
->elsewhere('', function ($browser) {
|
||||
$browser->click('[dusk="restore-selected-button"]')
|
||||
->elsewhereWhenAvailable(new Modals\RestoreResourceModalComponent(), function ($browser) {
|
||||
$browser->confirm();
|
||||
});
|
||||
})->pause(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the resources selected via checkboxes.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function forceDeleteSelected(Browser $browser)
|
||||
{
|
||||
$browser->click('@delete-menu')
|
||||
->pause(300)
|
||||
->elsewhere('', function ($browser) {
|
||||
$browser->click('[dusk="force-delete-selected-button"]')
|
||||
->elsewhereWhenAvailable(new Modals\DeleteResourceModalComponent(), function ($browser) {
|
||||
$browser->confirm();
|
||||
});
|
||||
})->pause(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser page contains the component.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->pause(500);
|
||||
|
||||
tap($this->selector(), function ($selector) use ($browser) {
|
||||
$browser->waitFor($selector)
|
||||
->assertVisible($selector)
|
||||
->scrollIntoView($selector);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given resource is visible.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @param int|string|null $pivotId
|
||||
* @return void
|
||||
*/
|
||||
public function assertSeeResource(Browser $browser, $id, $pivotId = null)
|
||||
{
|
||||
if (! is_null($pivotId)) {
|
||||
$browser->assertVisible('[dusk="'.$id.'-row"][data-pivot-id="'.$pivotId.'"]');
|
||||
} else {
|
||||
$browser->assertVisible("@{$id}-row");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given resource is not visible.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @param int|string|null $pivotId
|
||||
* @return void
|
||||
*/
|
||||
public function assertDontSeeResource(Browser $browser, $id, $pivotId = null)
|
||||
{
|
||||
if (! is_null($pivotId)) {
|
||||
$browser->assertMissing('[dusk="'.$id.'-row"][data-pivot-id="'.$pivotId.'"]');
|
||||
} else {
|
||||
$browser->assertMissing("@{$id}-row");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the checkbox is checked.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertCheckboxChecked(Browser $browser, $selector)
|
||||
{
|
||||
$browser->assertAttribute($selector, 'data-state', 'checked');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the checkbox is not checked.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertCheckboxNotChecked(Browser $browser, $selector)
|
||||
{
|
||||
$browser->assertAttribute($selector, 'data-state', 'unchecked');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the component.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'@nova-opened-modal' => '.modal[data-modal-open=true]',
|
||||
];
|
||||
}
|
||||
}
|
||||
31
nova/src/Testing/Browser/Components/LensComponent.php
Executable file
31
nova/src/Testing/Browser/Components/LensComponent.php
Executable file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components;
|
||||
|
||||
class LensComponent extends IndexComponent
|
||||
{
|
||||
public $lens;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param string $lens
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($resourceName, $lens)
|
||||
{
|
||||
$this->lens = $lens;
|
||||
$this->resourceName = $resourceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root selector for the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
return '@'.$this->lens.'-lens-component';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components\Modals;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class ConfirmActionModalComponent extends ModalComponent
|
||||
{
|
||||
/**
|
||||
* Modal confirmation button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function confirm(Browser $browser)
|
||||
{
|
||||
$browser->click('@confirm-action-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal cancelation button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(Browser $browser)
|
||||
{
|
||||
$browser->click('@cancel-action-button');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components\Modals;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class ConfirmUploadRemovalModalComponent extends ModalComponent
|
||||
{
|
||||
/**
|
||||
* Modal confirmation button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function confirm(Browser $browser)
|
||||
{
|
||||
$browser->click('@confirm-upload-delete-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal cancelation button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(Browser $browser)
|
||||
{
|
||||
$browser->click('@cancel-upload-delete-button');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components\Modals;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class CreateRelationModalComponent extends ModalComponent
|
||||
{
|
||||
/**
|
||||
* Modal confirmation button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function confirm(Browser $browser)
|
||||
{
|
||||
$browser->click('@create-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal cancelation button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(Browser $browser)
|
||||
{
|
||||
$browser->click('@cancel-create-button');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components\Modals;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class DeleteResourceModalComponent extends ModalComponent
|
||||
{
|
||||
/**
|
||||
* Modal confirmation button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function confirm(Browser $browser)
|
||||
{
|
||||
$browser->click('@confirm-delete-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal cancelation button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(Browser $browser)
|
||||
{
|
||||
$browser->click('@cancel-delete-button');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components\Modals;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Nova\Testing\Browser\Components\Component;
|
||||
|
||||
abstract class ModalComponent extends Component
|
||||
{
|
||||
/**
|
||||
* Get the root selector for the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
return '.modal[data-modal-open=true]';
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal confirmation button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
abstract public function confirm(Browser $browser);
|
||||
|
||||
/**
|
||||
* Modal cancelation button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
abstract public function cancel(Browser $browser);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components\Modals;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class PreviewResourceModalComponent extends ModalComponent
|
||||
{
|
||||
/**
|
||||
* Modal confirmation button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function confirm(Browser $browser)
|
||||
{
|
||||
$browser->click('@confirm-preview-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal cancelation button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(Browser $browser)
|
||||
{
|
||||
$browser->click('@confirm-preview-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal view detail button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function view(Browser $browser)
|
||||
{
|
||||
$browser->click('@detail-preview-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert modal view detail button is visible.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assertViewButtonVisible(Browser $browser)
|
||||
{
|
||||
$browser->assertVisible('@detail-preview-button');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components\Modals;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class RestoreResourceModalComponent extends ModalComponent
|
||||
{
|
||||
/**
|
||||
* Modal confirmation button.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function confirm(Browser $browser)
|
||||
{
|
||||
$browser->click('@confirm-restore-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal cancelation button.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(Browser $browser)
|
||||
{
|
||||
$browser->click('@cancel-restore-button');
|
||||
}
|
||||
}
|
||||
283
nova/src/Testing/Browser/Components/SearchInputComponent.php
Normal file
283
nova/src/Testing/Browser/Components/SearchInputComponent.php
Normal file
@@ -0,0 +1,283 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components;
|
||||
|
||||
use Facebook\WebDriver\WebDriverKeys;
|
||||
use Illuminate\Support\Arr;
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Dusk\ElementResolver;
|
||||
|
||||
class SearchInputComponent extends Component
|
||||
{
|
||||
public $attribute;
|
||||
|
||||
public $mode;
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param string $mode
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(string $attribute, string $mode = 'input')
|
||||
{
|
||||
$this->attribute = $attribute;
|
||||
$this->mode = $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the component dropdown.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function showSearchDropdown(Browser $browser)
|
||||
{
|
||||
$resolver = new ElementResolver($browser->driver, 'body');
|
||||
|
||||
$input = $resolver->find("[dusk='{$this->attribute}-search-{$this->mode}-dropdown']");
|
||||
|
||||
if (is_null($input) || ! $input->isDisplayed()) {
|
||||
$browser->click('');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the given value for a searchable field attribute.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $search
|
||||
* @param int $pause
|
||||
* @return void
|
||||
*/
|
||||
public function searchInput(Browser $browser, $search, int $pause = 500)
|
||||
{
|
||||
$this->showSearchDropdown($browser);
|
||||
|
||||
$browser->elsewhereWhenAvailable("{$this->selector()}-dropdown", function ($browser) use ($search) {
|
||||
$browser->type('input[type="search"]', $search);
|
||||
});
|
||||
|
||||
$browser->pause($pause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the searchable field.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function resetSearchResult(Browser $browser)
|
||||
{
|
||||
$this->cancelSelectingSearchResult($browser);
|
||||
|
||||
$selector = "{$this->selector()}-clear-button";
|
||||
|
||||
$element = $browser->element($selector);
|
||||
|
||||
if (! is_null($element) && $element->isDisplayed()) {
|
||||
$browser->click($selector)->pause(1500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search and select the searchable field by result index.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $search
|
||||
* @param int $resultIndex
|
||||
* @return void
|
||||
*/
|
||||
public function searchAndSelectResult(Browser $browser, $search, $resultIndex)
|
||||
{
|
||||
$this->searchInput($browser, $search, 1500);
|
||||
|
||||
$this->selectSearchResult($browser, $resultIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the searchable field by result index.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param int $resultIndex
|
||||
* @return void
|
||||
*/
|
||||
public function selectSearchResult(Browser $browser, $resultIndex)
|
||||
{
|
||||
$browser->elseWhereWhenAvailable("{$this->selector()}-dropdown", function ($browser) use ($resultIndex) {
|
||||
$browser->whenAvailable("{$this->selector()}-result-{$resultIndex}", function ($browser) {
|
||||
$browser->click('')->pause(300);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the currently highlighted searchable field.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function cancelSelectingSearchResult(Browser $browser)
|
||||
{
|
||||
$browser->driver->getKeyboard()->sendKeys(WebDriverKeys::ESCAPE);
|
||||
|
||||
$browser->pause(150);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the currently highlighted searchable field.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function selectFirstSearchResult(Browser $browser)
|
||||
{
|
||||
$this->selectSearchResult($browser, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search and select the currently highlighted searchable relation.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function searchFirstRelation(Browser $browser, $search)
|
||||
{
|
||||
$this->searchAndSelectFirstResult($browser, $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search and select the currently highlighted searchable field.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function searchAndSelectFirstResult(Browser $browser, $search)
|
||||
{
|
||||
$this->searchAndSelectResult($browser, $search, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param callable(\Laravel\Nova\Browser, string):void $fieldCallback
|
||||
* @return void
|
||||
*/
|
||||
public function assertSearchResult(Browser $browser, callable $fieldCallback)
|
||||
{
|
||||
$this->showSearchDropdown($browser);
|
||||
|
||||
$browser->elsewhereWhenAvailable("{$this->selector()}-dropdown", function ($browser) use ($fieldCallback) {
|
||||
$fieldCallback($browser, $this->selector());
|
||||
|
||||
$this->cancelSelectingSearchResult($browser);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results is locked to single result.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function assertSelectedSearchResult(Browser $browser, $search)
|
||||
{
|
||||
$browser->assertSeeIn("{$this->selector()}-selected", $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results is locked to single result.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function assertSelectedFirstSearchResult(Browser $browser, $search)
|
||||
{
|
||||
$this->assertSelectedSearchResult($browser, $search);
|
||||
|
||||
$this->assertSearchResult($browser, function ($browser, $attribute) use ($search) {
|
||||
$browser->assertSeeIn("{$attribute}-result-0", $search)
|
||||
->assertNotPresent("{$attribute}-result-1")
|
||||
->assertNotPresent("{$attribute}-result-2")
|
||||
->assertNotPresent("{$attribute}-result-3")
|
||||
->assertNotPresent("{$attribute}-result-4");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results is empty.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assertEmptySearchResult(Browser $browser)
|
||||
{
|
||||
$this->assertSearchResult($browser, function ($browser, $attribute) {
|
||||
$browser->assertNotPresent("{$attribute}-result-0")
|
||||
->assertNotPresent("{$attribute}-result-1")
|
||||
->assertNotPresent("{$attribute}-result-2")
|
||||
->assertNotPresent("{$attribute}-result-3")
|
||||
->assertNotPresent("{$attribute}-result-4");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results has the search value.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string|array $search
|
||||
* @return void
|
||||
*/
|
||||
public function assertSearchResultContains(Browser $browser, $search)
|
||||
{
|
||||
$this->assertSearchResult($browser, function ($browser, $attribute) use ($search) {
|
||||
foreach (Arr::wrap($search) as $keyword) {
|
||||
$browser->assertSeeIn("{$attribute}-results", $keyword);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results doesn't has the search value.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string|array $search
|
||||
* @return void
|
||||
*/
|
||||
public function assertSearchResultDoesNotContains(Browser $browser, $search)
|
||||
{
|
||||
$this->assertSearchResult($browser, function ($browser, $attribute) use ($search) {
|
||||
foreach (Arr::wrap($search) as $keyword) {
|
||||
$browser->assertDontSeeIn("{$attribute}-results", $keyword);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current page contains this component.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->waitFor($this->selector());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root selector associated with this component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
return "@{$this->attribute}-search-{$this->mode}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class SearchSearchInputComponent extends SearchInputComponent
|
||||
{
|
||||
/**
|
||||
* Search for the given value for a searchable field attribute.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function searchInput(Browser $browser, $search, int $pause = 500)
|
||||
{
|
||||
$this->showSearchDropdown($browser);
|
||||
|
||||
$browser->type('input[type="search"]', $search);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class SelectAllDropdownComponent extends Component
|
||||
{
|
||||
/**
|
||||
* Get the root selector for the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
return '@select-all-dropdown';
|
||||
}
|
||||
|
||||
protected function assertCheckboxStatus(Browser $browser, $status)
|
||||
{
|
||||
$browser->assertAttribute('@select-all-indicator', 'data-state', $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the checkbox is checked.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertCheckboxIsChecked(Browser $browser)
|
||||
{
|
||||
$this->assertCheckboxStatus($browser, 'checked');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the checkbox is not checked.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertCheckboxIsNotChecked(Browser $browser)
|
||||
{
|
||||
$this->assertCheckboxStatus($browser, 'unchecked');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the checkbox is indeterminate.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertCheckboxIsIndeterminate(Browser $browser)
|
||||
{
|
||||
$this->assertCheckboxStatus($browser, 'indeterminate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert select all the the resources on current page is checked.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertSelectAllOnCurrentPageChecked(Browser $browser)
|
||||
{
|
||||
$this->assertCheckboxIsIndeterminate($browser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert select all the the resources on current page isn't checked.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertSelectAllOnCurrentPageNotChecked(Browser $browser)
|
||||
{
|
||||
$this->assertCheckboxIsNotChecked($browser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert select all the matching resources is checked.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertSelectAllMatchingChecked(Browser $browser)
|
||||
{
|
||||
$browser
|
||||
->waitFor('@select-all-dropdown-trigger')
|
||||
->click('@select-all-dropdown-trigger')
|
||||
->elsewhereWhenAvailable('@dropdown-menu', function (Browser $browser) {
|
||||
$browser->assertAttribute('@select-all-matching-button', 'data-state', 'checked');
|
||||
})
|
||||
->closeCurrentDropdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert select all the matching resources isn't checked.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertSelectAllMatchingNotChecked(Browser $browser)
|
||||
{
|
||||
$browser
|
||||
->waitFor('@select-all-dropdown-trigger')
|
||||
->click('@select-all-dropdown-trigger')
|
||||
->elsewhereWhenAvailable('@dropdown-menu', function (Browser $browser) {
|
||||
$browser->assertAttribute('@select-all-matching-button', 'data-state', 'unchecked');
|
||||
})
|
||||
->closeCurrentDropdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on the total selected count text.
|
||||
*
|
||||
* @param int $count
|
||||
* @return void
|
||||
*/
|
||||
public function assertSelectedCount(Browser $browser, $count)
|
||||
{
|
||||
$browser->assertSeeIn('span.font-bold', "{$count} selected");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on the matching total matching count text.
|
||||
*
|
||||
* @param int $count
|
||||
* @return void
|
||||
*/
|
||||
public function assertSelectAllMatchingCount(Browser $browser, $count)
|
||||
{
|
||||
$browser
|
||||
->waitFor('@select-all-dropdown-trigger')
|
||||
->click('@select-all-dropdown-trigger')
|
||||
->elsewhereWhenAvailable('@dropdown-menu', function (Browser $browser) use ($count) {
|
||||
$browser->assertSeeIn('@select-all-matching-count', $count);
|
||||
})
|
||||
->closeCurrentDropdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Select all the the resources on current page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function selectAllOnCurrentPage(Browser $browser)
|
||||
{
|
||||
$browser
|
||||
->waitFor('@select-all-dropdown-trigger')
|
||||
->click('@select-all-dropdown-trigger')
|
||||
->elsewhereWhenAvailable('@dropdown-menu', function ($browser) {
|
||||
$browser->click('@select-all-button');
|
||||
})
|
||||
->closeCurrentDropdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Un-select all the the resources on current page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unselectAllOnCurrentPage(Browser $browser)
|
||||
{
|
||||
$browser->waitFor('@deselect-all-button')
|
||||
->click('@deselect-all-button')->pause(250);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select all the matching resources.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function selectAllMatching(Browser $browser)
|
||||
{
|
||||
$browser
|
||||
->waitFor('@select-all-dropdown-trigger')
|
||||
->click('@select-all-dropdown-trigger')
|
||||
->elsewhereWhenAvailable('@dropdown-menu', function ($browser) {
|
||||
$browser->click('@select-all-matching-button');
|
||||
})
|
||||
->closeCurrentDropdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Un-select all the matching resources.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unselectAllMatching(Browser $browser)
|
||||
{
|
||||
$browser
|
||||
->waitFor('@select-all-dropdown-trigger', 2)
|
||||
->click('@select-all-dropdown-trigger')
|
||||
->elsewhereWhenAvailable('@dropdown-menu', function ($browser) {
|
||||
$browser->click('@select-all-matching-button')->pause(250);
|
||||
}, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser page contains the component.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
tap($this->selector(), function ($selector) use ($browser) {
|
||||
$browser->scrollIntoView($selector);
|
||||
});
|
||||
}
|
||||
}
|
||||
63
nova/src/Testing/Browser/Components/SidebarComponent.php
Normal file
63
nova/src/Testing/Browser/Components/SidebarComponent.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Components;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class SidebarComponent extends Component
|
||||
{
|
||||
/**
|
||||
* The screen size 'desktop', 'responsive'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $screen = 'desktop';
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*
|
||||
* @param string|null $screen
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($screen = null)
|
||||
{
|
||||
$this->screen = $screen ?? $this->screen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root selector for the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function selector()
|
||||
{
|
||||
return 'div[dusk="sidebar-menu"][role="navigation"][data-screen="'.$this->screen.'"]';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser page contains the component.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
tap($this->selector(), function ($selector) use ($browser) {
|
||||
$browser->scrollIntoView($selector);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the component.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'@current-active-link' => 'a[data-active-link=true]',
|
||||
];
|
||||
}
|
||||
}
|
||||
145
nova/src/Testing/Browser/Concerns/InteractsWithElements.php
Normal file
145
nova/src/Testing/Browser/Concerns/InteractsWithElements.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Concerns;
|
||||
|
||||
use Carbon\CarbonInterface;
|
||||
use Facebook\WebDriver\Exception\WebDriverException;
|
||||
use Illuminate\Support\Env;
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
trait InteractsWithElements
|
||||
{
|
||||
/**
|
||||
* Dismiss toasted messages.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dismissToasted(Browser $browser)
|
||||
{
|
||||
$browser->script('Nova.$toasted.clear()');
|
||||
}
|
||||
|
||||
/**
|
||||
* Close current dropdown.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function closeCurrentDropdown(Browser $browser, bool $throwIfMissing = false)
|
||||
{
|
||||
try {
|
||||
$browser->elseWhereWhenAvailable('@dropdown-teleported', function (Browser $browser) {
|
||||
$element = $browser->element('@dropdown-overlay');
|
||||
|
||||
if (! is_null($element) && $element->isDisplayed()) {
|
||||
$browser->click('@dropdown-overlay')->waitUntilMissing('@dropdown-overlay');
|
||||
}
|
||||
});
|
||||
} catch (WebDriverException $e) {
|
||||
if ($throwIfMissing === true) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type on "date" input.
|
||||
*
|
||||
* @param \Carbon\CarbonInterface|empty-string|null $carbon
|
||||
* @return void
|
||||
*/
|
||||
public function typeOnDate(Browser $browser, string $selector, $carbon)
|
||||
{
|
||||
if ($carbon instanceof CarbonInterface) {
|
||||
$date = $carbon->format(Env::get('DUSK_DATE_FORMAT', 'mdY'));
|
||||
|
||||
$this->typeWithTabs($browser, $selector, $date);
|
||||
} else {
|
||||
$browser->type($selector, '');
|
||||
}
|
||||
|
||||
$browser->pause(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Type in a "datetime" filter input.
|
||||
*
|
||||
* @param \Carbon\CarbonInterface|empty-string|null $carbon
|
||||
* @return void
|
||||
*/
|
||||
public function typeInDateTimeField(Browser $browser, string $selector, $carbon)
|
||||
{
|
||||
if ($carbon instanceof CarbonInterface) {
|
||||
$this->typeWithTabs($browser, $selector, $carbon->format(Env::get('DUSK_DATETIME_FORMAT', 'mdY-hia')));
|
||||
$browser->keys($selector, ['{tab}']);
|
||||
} else {
|
||||
$browser->type($selector, '');
|
||||
}
|
||||
|
||||
$browser->pause(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Type on "datetime-local" input.
|
||||
*
|
||||
* @param \Carbon\CarbonInterface|empty-string|null $carbon
|
||||
* @return void
|
||||
*/
|
||||
public function typeOnDateTimeLocal(Browser $browser, string $selector, $carbon)
|
||||
{
|
||||
if ($carbon instanceof CarbonInterface) {
|
||||
$date = $carbon->format(Env::get('DUSK_DATE_FORMAT', 'mdY'));
|
||||
$time = $carbon->format(Env::get('DUSK_TIME_FORMAT', 'hisa'));
|
||||
|
||||
$this->typeWithTabs($browser, $selector, $date);
|
||||
$browser->keys($selector, ['{tab}']);
|
||||
$this->typeWithTabs($browser, $selector, $time);
|
||||
} else {
|
||||
$browser->type($selector, '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type input separated using "tab".
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function typeWithTabs(Browser $browser, string $selector, string $date, string $separator = '-')
|
||||
{
|
||||
$date = explode($separator, $date);
|
||||
|
||||
array_map(function ($group) use ($date, $browser, $selector) {
|
||||
if (strtolower($group) === 'am') {
|
||||
$browser->type($selector, 'a');
|
||||
} elseif (strtolower($group) === 'pm') {
|
||||
$browser->type($selector, 'p');
|
||||
} else {
|
||||
$browser->type($selector, $group);
|
||||
}
|
||||
|
||||
// if the item is not the last in the array, let's tab through
|
||||
if ($group !== end($date)) {
|
||||
$browser->keys($selector, ['{tab}']);
|
||||
}
|
||||
}, $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert active modal is present.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertPresentModal(Browser $browser)
|
||||
{
|
||||
$browser->assertPresent('.modal[data-modal-open=true]');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert active modal is missing.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertMissingModal(Browser $browser)
|
||||
{
|
||||
$browser->assertMissing('.modal[data-modal-open=true]');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Concerns;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Nova\Testing\Browser\Components\Modals\CreateRelationModalComponent;
|
||||
|
||||
trait InteractsWithInlineCreateRelation
|
||||
{
|
||||
/**
|
||||
* Run the inline relation.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $uriKey
|
||||
* @param callable $fieldCallback
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function showInlineCreate(Browser $browser, string $uriKey, callable $fieldCallback)
|
||||
{
|
||||
$browser->whenAvailable("@{$uriKey}-inline-create", function ($browser) use ($fieldCallback) {
|
||||
$browser->click('')
|
||||
->elsewhereWhenAvailable(new CreateRelationModalComponent(), function ($browser) use ($fieldCallback) {
|
||||
$fieldCallback($browser);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the inline create relation.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $uriKey
|
||||
* @param callable $fieldCallback
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function runInlineCreate(Browser $browser, string $uriKey, callable $fieldCallback)
|
||||
{
|
||||
$this->showInlineCreate($browser, $uriKey, function ($browser) use ($fieldCallback) {
|
||||
$fieldCallback($browser);
|
||||
|
||||
$browser->click('@create-button')->pause(250);
|
||||
});
|
||||
}
|
||||
}
|
||||
158
nova/src/Testing/Browser/Pages/Attach.php
Executable file
158
nova/src/Testing/Browser/Pages/Attach.php
Executable file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Nova\Testing\Browser\Components\SearchInputComponent;
|
||||
|
||||
class Attach extends Page
|
||||
{
|
||||
use InteractsWithRelations;
|
||||
|
||||
public $resourceName;
|
||||
|
||||
public $resourceId;
|
||||
|
||||
public $relation;
|
||||
|
||||
public $viaRelationship;
|
||||
|
||||
public $polymorphic = false;
|
||||
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param string $resourceId
|
||||
* @param string $relation
|
||||
* @param string|null $viaRelationship
|
||||
* @param bool $polymorphic
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($resourceName, $resourceId, $relation, $viaRelationship = null, $polymorphic = false)
|
||||
{
|
||||
$this->relation = $relation;
|
||||
$this->resourceId = $resourceId;
|
||||
$this->resourceName = $resourceName;
|
||||
$this->viaRelationship = $viaRelationship;
|
||||
$this->polymorphic = $polymorphic;
|
||||
|
||||
$this->setNovaPage("/resources/{$this->resourceName}/{$this->resourceId}/attach/{$this->relation}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new page instance for Belongs-to-Many.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param string $resourceId
|
||||
* @param string $relation
|
||||
* @param string|null $viaRelationship
|
||||
* @return static
|
||||
*/
|
||||
public static function belongsToMany($resourceName, $resourceId, $relation, $viaRelationship = null)
|
||||
{
|
||||
return new static($resourceName, $resourceId, $relation, $viaRelationship);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new page instance for Morph-to-Many.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param string $resourceId
|
||||
* @param string $relation
|
||||
* @param string|null $viaRelationship
|
||||
* @return static
|
||||
*/
|
||||
public static function morphToMany($resourceName, $resourceId, $relation, $viaRelationship = null)
|
||||
{
|
||||
return new static($resourceName, $resourceId, $relation, $viaRelationship, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL for the page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return $this->novaPageUrl.'?'.http_build_query([
|
||||
'viaRelationship' => $this->viaRelationship ?? $this->relation,
|
||||
'polymorphic' => $this->polymorphic === true ? 1 : 0,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the attachable resource with the given ID.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string|int $id
|
||||
* @return void
|
||||
*/
|
||||
public function selectAttachable(Browser $browser, $id)
|
||||
{
|
||||
$this->selectRelation($browser, 'attachable', $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the attachable resource with the given ID.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string|int $id
|
||||
* @return void
|
||||
*/
|
||||
public function searchAttachable(Browser $browser, $id)
|
||||
{
|
||||
$browser->within(new SearchInputComponent($this->relation), function ($browser) use ($id) {
|
||||
$browser->searchFirstRelation($id);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the attach button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function create(Browser $browser)
|
||||
{
|
||||
$browser->dismissToasted()
|
||||
->click('@attach-button')
|
||||
->pause(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the update and continue editing button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function createAndAttachAnother(Browser $browser)
|
||||
{
|
||||
$browser->dismissToasted()
|
||||
->click('@attach-and-attach-another-button')
|
||||
->pause(750);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the cancel button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(Browser $browser)
|
||||
{
|
||||
$browser->dismissToasted()
|
||||
->click('@cancel-attach-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertOk()->waitFor('@nova-form');
|
||||
}
|
||||
}
|
||||
88
nova/src/Testing/Browser/Pages/Create.php
Executable file
88
nova/src/Testing/Browser/Pages/Create.php
Executable file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class Create extends Page
|
||||
{
|
||||
use InteractsWithRelations;
|
||||
|
||||
public $resourceName;
|
||||
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param array $queryParams
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($resourceName, $queryParams = [])
|
||||
{
|
||||
$this->resourceName = $resourceName;
|
||||
$this->queryParams = $queryParams;
|
||||
|
||||
$this->setNovaPage("/resources/{$this->resourceName}/new");
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the create button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function create(Browser $browser)
|
||||
{
|
||||
$browser->dismissToasted()
|
||||
->click('@create-button')
|
||||
->pause(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the create and add another button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function createAndAddAnother(Browser $browser)
|
||||
{
|
||||
$browser->dismissToasted()
|
||||
->click('@create-and-add-another-button')
|
||||
->pause(500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the cancel button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(Browser $browser)
|
||||
{
|
||||
$browser->dismissToasted()
|
||||
->click('@cancel-create-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertOk()->waitFor('@nova-form');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that there are no search results.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $resourceName
|
||||
* @return void
|
||||
*/
|
||||
public function assertNoRelationSearchResults(Browser $browser, $resourceName)
|
||||
{
|
||||
$browser->assertMissing('@'.$resourceName.'-search-input-result-0');
|
||||
}
|
||||
}
|
||||
46
nova/src/Testing/Browser/Pages/Dashboard.php
Normal file
46
nova/src/Testing/Browser/Pages/Dashboard.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class Dashboard extends Page
|
||||
{
|
||||
public $dashboardName;
|
||||
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @param string $dashboardName
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($dashboardName = 'main')
|
||||
{
|
||||
$this->dashboardName = $dashboardName;
|
||||
|
||||
$this->setNovaPage("/dashboards/{$this->dashboardName}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertOk()->waitFor('@nova-dashboard');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'@nova-dashboard' => "[dusk='dashboard-{$this->dashboardName}']",
|
||||
];
|
||||
}
|
||||
}
|
||||
242
nova/src/Testing/Browser/Pages/Detail.php
Executable file
242
nova/src/Testing/Browser/Pages/Detail.php
Executable file
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Nova\Testing\Browser\Components\ActionDropdownComponent;
|
||||
use Laravel\Nova\Testing\Browser\Components\IndexComponent;
|
||||
use Laravel\Nova\Testing\Browser\Components\Modals\DeleteResourceModalComponent;
|
||||
use Laravel\Nova\Testing\Browser\Components\Modals\RestoreResourceModalComponent;
|
||||
|
||||
class Detail extends Page
|
||||
{
|
||||
public $resourceName;
|
||||
|
||||
public $resourceId;
|
||||
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param string $resourceId
|
||||
* @param array $queryParams
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($resourceName, $resourceId, $queryParams = [])
|
||||
{
|
||||
$this->resourceId = $resourceId;
|
||||
$this->resourceName = $resourceName;
|
||||
$this->queryParams = $queryParams;
|
||||
|
||||
$this->setNovaPage("/resources/{$this->resourceName}/{$this->resourceId}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the action with the given URI key.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $uriKey
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function runAction(Browser $browser, $uriKey)
|
||||
{
|
||||
$browser->openControlSelector()
|
||||
->elsewhereWhenAvailable(new ActionDropdownComponent(), function ($browser) use ($uriKey) {
|
||||
$browser->runWithConfirmation($uriKey);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the action with the given URI key.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $uriKey
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function runInstantAction(Browser $browser, $uriKey)
|
||||
{
|
||||
$browser->openControlSelector()
|
||||
->elsewhereWhenAvailable(new ActionDropdownComponent(), function ($browser) use ($uriKey) {
|
||||
$browser->runWithoutConfirmation($uriKey);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the action modal but cancel the action.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $uriKey
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function cancelAction(Browser $browser, $uriKey)
|
||||
{
|
||||
$browser->openControlSelector()
|
||||
->elsewhereWhenAvailable(new ActionDropdownComponent(), function ($browser) use ($uriKey) {
|
||||
$browser->cancel($uriKey);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit the resource.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function edit(Browser $browser)
|
||||
{
|
||||
$browser->waitFor('@edit-resource-button')
|
||||
->click('@edit-resource-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the related resource.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $relatedResourceName
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function runCreateRelation(Browser $browser, $relatedResourceName)
|
||||
{
|
||||
$browser->within(new IndexComponent($relatedResourceName), function ($browser) {
|
||||
$browser->waitFor('@create-button')->click('@create-button');
|
||||
})->on(new Create($relatedResourceName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the related resource.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $relatedResourceName
|
||||
* @param string|null $viaRelationship
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function runAttachRelation(Browser $browser, $relatedResourceName, $viaRelationship = null)
|
||||
{
|
||||
$browser->within(new IndexComponent($relatedResourceName, $viaRelationship), function ($browser) {
|
||||
$browser->waitFor('@attach-button')->click('@attach-button');
|
||||
})->on(new Attach($this->resourceName, $this->resourceId, $relatedResourceName, $viaRelationship));
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the delete selector.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function openControlSelector(Browser $browser)
|
||||
{
|
||||
$browser->whenAvailable("@{$this->resourceId}-control-selector", function ($browser) {
|
||||
$browser->click('');
|
||||
})->pause(100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replicate the resource.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function replicate(Browser $browser)
|
||||
{
|
||||
$browser->openControlSelector()
|
||||
->whenAvailable("@{$this->resourceId}-replicate-button", function ($browser) {
|
||||
$browser->click('');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the resource.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function delete(Browser $browser)
|
||||
{
|
||||
$browser->openControlSelector()
|
||||
->whenAvailable('@open-delete-modal-button', function ($browser) {
|
||||
$browser->click('');
|
||||
})
|
||||
->elsewhereWhenAvailable(new DeleteResourceModalComponent(), function ($browser) {
|
||||
$browser->confirm();
|
||||
})->pause(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the resource.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function restore(Browser $browser)
|
||||
{
|
||||
$browser->openControlSelector()
|
||||
->whenAvailable('@open-restore-modal-button', function ($browser) {
|
||||
$browser->click('');
|
||||
})
|
||||
->elsewhereWhenAvailable(new RestoreResourceModalComponent(), function ($browser) {
|
||||
$browser->confirm();
|
||||
})->pause(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force delete the resource.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function forceDelete(Browser $browser)
|
||||
{
|
||||
$browser->openControlSelector()
|
||||
->whenAvailable('@open-force-delete-modal-button', function ($browser) {
|
||||
$browser->click('');
|
||||
})
|
||||
->elsewhereWhenAvailable(new DeleteResourceModalComponent(), function ($browser) {
|
||||
$browser->confirm();
|
||||
})->pause(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertOk()->waitFor('@nova-resource-detail');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'@nova-resource-detail' => '[dusk="'.$this->resourceName.'-detail-component"]',
|
||||
];
|
||||
}
|
||||
}
|
||||
31
nova/src/Testing/Browser/Pages/Forbidden.php
Normal file
31
nova/src/Testing/Browser/Pages/Forbidden.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class Forbidden extends Page
|
||||
{
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('/403');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->whenAvailable('@403-error-page', function ($browser) {
|
||||
$browser->assertSee('403');
|
||||
});
|
||||
}
|
||||
}
|
||||
214
nova/src/Testing/Browser/Pages/HasSearchable.php
Normal file
214
nova/src/Testing/Browser/Pages/HasSearchable.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Nova\Testing\Browser\Components\SearchInputComponent;
|
||||
|
||||
trait HasSearchable
|
||||
{
|
||||
/**
|
||||
* Search for the given value for a searchable field attribute.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param string $search
|
||||
* @param int $pause
|
||||
* @return void
|
||||
*/
|
||||
public function searchInput(Browser $browser, $attribute, $search, int $pause = 500)
|
||||
{
|
||||
$browser->whenAvailable(new SearchInputComponent($attribute), function ($browser) use ($search, $pause) {
|
||||
$browser->searchInput($search, $pause);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the searchable field.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param int $resultIndex
|
||||
* @return void
|
||||
*/
|
||||
public function resetSearchResult(Browser $browser, $attribute)
|
||||
{
|
||||
$browser->whenAvailable(new SearchInputComponent($attribute), function ($browser) {
|
||||
$browser->resetSearchResult();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the searchable field by result index.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param int $resultIndex
|
||||
* @return void
|
||||
*/
|
||||
public function selectSearchResult(Browser $browser, $attribute, $resultIndex)
|
||||
{
|
||||
$browser->whenAvailable(new SearchInputComponent($attribute), function ($browser) use ($resultIndex) {
|
||||
$browser->selectSearchResult($resultIndex);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the currently highlighted searchable field.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @return void
|
||||
*/
|
||||
public function selectFirstSearchResult(Browser $browser, $attribute)
|
||||
{
|
||||
$this->selectSearchResult($browser, $attribute, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the currently highlighted searchable field.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @return void
|
||||
*/
|
||||
public function cancelSelectingSearchResult(Browser $browser, $attribute)
|
||||
{
|
||||
$browser->whenAvailable(new SearchInputComponent($attribute), function ($browser) {
|
||||
$browser->cancelSelectingSearchResult();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Search and select the searchable field by result index.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param string $search
|
||||
* @param int $resultIndex
|
||||
* @return void
|
||||
*/
|
||||
public function searchAndSelectResult(Browser $browser, $attribute, $search, $resultIndex)
|
||||
{
|
||||
$browser->whenAvailable(new SearchInputComponent($attribute), function ($browser) use ($search, $resultIndex) {
|
||||
$browser->searchAndSelectResult($search, $resultIndex);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Search and select the currently highlighted searchable field.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function searchAndSelectFirstResult(Browser $browser, $attribute, $search)
|
||||
{
|
||||
$this->searchAndSelectResult($browser, $attribute, $search, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param callable(\Laravel\Nova\Browser, string):void $fieldCallback
|
||||
* @return void
|
||||
*/
|
||||
public function assertSearchResult(Browser $browser, $attribute, callable $fieldCallback)
|
||||
{
|
||||
$browser->whenAvailable(new SearchInputComponent($attribute), function ($browser) use ($fieldCallback) {
|
||||
$browser->assertSearchResult($search, $fieldCallback);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results current value.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function assertSelectedSearchResult(Browser $browser, $attribute, $search)
|
||||
{
|
||||
$browser->whenAvailable(new SearchInputComponent($attribute), function ($browser) use ($search) {
|
||||
$browser->assertSelectedSearchResult($search);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results is locked to single result.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function assertSelectedFirstSearchResult(Browser $browser, $attribute, $search)
|
||||
{
|
||||
$browser->whenAvailable(new SearchInputComponent($attribute), function ($browser) use ($search) {
|
||||
$browser->assertSelectedFirstSearchResult($search);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results is empty.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @return void
|
||||
*/
|
||||
public function assertEmptySearchResult(Browser $browser, $attribute)
|
||||
{
|
||||
$browser->whenAvailable(new SearchInputComponent($attribute), function ($browser) {
|
||||
$browser->assertEmptySearchResult();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results has the search value.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param string|array $search
|
||||
* @return void
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function assertSearchResultHas(Browser $browser, $attribute, $search)
|
||||
{
|
||||
$this->assertSearchResultContains($browser, $attribute, $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results has the search value.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param string|array $search
|
||||
* @return void
|
||||
*/
|
||||
public function assertSearchResultContains(Browser $browser, $attribute, $search)
|
||||
{
|
||||
$browser->whenAvailable(new SearchInputComponent($attribute), function ($browser) use ($search) {
|
||||
$browser->assertSearchResultContains($search);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert on searchable results doesn't has the search value.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param string|array $search
|
||||
* @return void
|
||||
*/
|
||||
public function assertSearchResultDoesNotContains(Browser $browser, $attribute, $search)
|
||||
{
|
||||
$browser->whenAvailable(new SearchInputComponent($attribute), function ($browser) use ($search) {
|
||||
$browser->assertSearchResultDoesNotContains($search);
|
||||
});
|
||||
}
|
||||
}
|
||||
16
nova/src/Testing/Browser/Pages/HomePage.php
Executable file
16
nova/src/Testing/Browser/Pages/HomePage.php
Executable file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
class HomePage extends Page
|
||||
{
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('/');
|
||||
}
|
||||
}
|
||||
72
nova/src/Testing/Browser/Pages/Index.php
Executable file
72
nova/src/Testing/Browser/Pages/Index.php
Executable file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Nova\Testing\Browser\Components\FormComponent;
|
||||
use Laravel\Nova\Testing\Browser\Components\IndexComponent;
|
||||
|
||||
class Index extends Page
|
||||
{
|
||||
public $resourceName;
|
||||
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param array $queryParams
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($resourceName, $queryParams = [])
|
||||
{
|
||||
$this->resourceName = $resourceName;
|
||||
$this->queryParams = $queryParams;
|
||||
|
||||
$this->setNovaPage("/resources/{$this->resourceName}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the related resource.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param \Closure|null $fieldCallback
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function runCreate(Browser $browser, $fieldCallback = null)
|
||||
{
|
||||
$browser->within(new IndexComponent($this->resourceName), function ($browser) {
|
||||
$browser->waitFor('@create-button')->click('@create-button');
|
||||
})->on(new Create($this->resourceName));
|
||||
|
||||
if (! is_null($fieldCallback)) {
|
||||
$browser->within(new FormComponent(), function ($browser) use ($fieldCallback) {
|
||||
call_user_func($fieldCallback, $browser);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertOk()->waitFor('@nova-resource-index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'@nova-resource-index' => '[dusk="'.$this->resourceName.'-index-component"]',
|
||||
];
|
||||
}
|
||||
}
|
||||
147
nova/src/Testing/Browser/Pages/InteractsWithRelations.php
Executable file
147
nova/src/Testing/Browser/Pages/InteractsWithRelations.php
Executable file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Nova\Testing\Browser\Components\Controls\RelationSelectControlComponent;
|
||||
use Laravel\Nova\Testing\Browser\Concerns\InteractsWithInlineCreateRelation;
|
||||
|
||||
trait InteractsWithRelations
|
||||
{
|
||||
use HasSearchable;
|
||||
use InteractsWithInlineCreateRelation;
|
||||
|
||||
/**
|
||||
* Select for the given value for a relationship attribute.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param string|null $value
|
||||
* @return void
|
||||
*/
|
||||
public function selectRelation(Browser $browser, $attribute, $value = null)
|
||||
{
|
||||
$browser->whenAvailable(new RelationSelectControlComponent($attribute), function (Browser $browser) use ($value) {
|
||||
$browser->assertSelectHasOption('', $value)->select('', $value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the given value for a searchable relationship attribute.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function searchRelation(Browser $browser, $attribute, $search)
|
||||
{
|
||||
$this->searchInput($browser, $attribute, $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the searchable relationship attribute.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @return void
|
||||
*/
|
||||
public function resetSearchRelation(Browser $browser, $attribute)
|
||||
{
|
||||
$this->resetSearchResult($browser, $attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the currently highlighted searchable relation.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @return void
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function selectFirstRelation(Browser $browser, $attribute)
|
||||
{
|
||||
$this->selectFirstSearchResult($browser, $attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the currently highlighted searchable relation.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @return void
|
||||
*/
|
||||
public function firstSearchableResult(Browser $browser, $attribute)
|
||||
{
|
||||
$this->selectFirstSearchResult($browser, $attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the searchable relation result.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @return void
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function closeSearchableResult(Browser $browser, $attribute)
|
||||
{
|
||||
$this->cancelSelectingSearchResult($browser, $attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search and select the currently highlighted searchable relation.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $attribute
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function searchFirstRelation(Browser $browser, $attribute, $search)
|
||||
{
|
||||
$this->searchAndSelectFirstResult($browser, $attribute, $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that trashed relations should be included in the search results.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $resourceName
|
||||
* @return void
|
||||
*/
|
||||
public function waitForTrashedRelation(Browser $browser, $resourceName)
|
||||
{
|
||||
$browser->waitFor("@{$resourceName}-with-trashed-checkbox", 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that trashed relations should be included in the search results.
|
||||
*/
|
||||
public function withTrashedRelation(Browser $browser, $resourceName)
|
||||
{
|
||||
$browser->waitForTrashedRelation($resourceName)->click('')->with(
|
||||
"@{$resourceName}-with-trashed-checkbox",
|
||||
function (Browser $browser) {
|
||||
$browser->waitFor('input[type="checkbox"]')
|
||||
->check('input[type="checkbox"]')
|
||||
->pause(250);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that trashed relations should not be included in the search results.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $resourceName
|
||||
* @return void
|
||||
*/
|
||||
public function withoutTrashedRelation(Browser $browser, $resourceName)
|
||||
{
|
||||
$browser->waitForTrashedRelation($resourceName)
|
||||
->uncheck('[dusk="'.$resourceName.'-with-trashed-checkbox"] input[type="checkbox"]')
|
||||
->pause(250);
|
||||
}
|
||||
}
|
||||
50
nova/src/Testing/Browser/Pages/Lens.php
Executable file
50
nova/src/Testing/Browser/Pages/Lens.php
Executable file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class Lens extends Index
|
||||
{
|
||||
public $lens;
|
||||
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param string $lens
|
||||
* @param array $queryParams
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($resourceName, $lens, $queryParams = [])
|
||||
{
|
||||
$this->lens = $lens;
|
||||
$this->resourceName = $resourceName;
|
||||
$this->queryParams = $queryParams;
|
||||
|
||||
$this->setNovaPage("/resources/{$this->resourceName}/lens/{$this->lens}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertOk()->waitFor('@nova-resource-lens');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'@nova-resource-lens' => '[dusk="'.$this->lens.'-lens-component"]',
|
||||
];
|
||||
}
|
||||
}
|
||||
40
nova/src/Testing/Browser/Pages/Login.php
Normal file
40
nova/src/Testing/Browser/Pages/Login.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class Login extends Page
|
||||
{
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('/login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertOk();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert page not found.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assertOk(Browser $browser)
|
||||
{
|
||||
$browser->waitForLocation($this->novaPageUrl)->assertPathIs($this->novaPageUrl);
|
||||
}
|
||||
}
|
||||
31
nova/src/Testing/Browser/Pages/NotFound.php
Normal file
31
nova/src/Testing/Browser/Pages/NotFound.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class NotFound extends Page
|
||||
{
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('/404');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->whenAvailable('@404-error-page', function ($browser) {
|
||||
$browser->assertSee('404');
|
||||
});
|
||||
}
|
||||
}
|
||||
124
nova/src/Testing/Browser/Pages/Page.php
Normal file
124
nova/src/Testing/Browser/Pages/Page.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Dusk\Page as Dusk;
|
||||
use Laravel\Nova\Nova;
|
||||
use Laravel\Nova\Testing\Browser\Concerns\InteractsWithElements;
|
||||
|
||||
class Page extends Dusk
|
||||
{
|
||||
use InteractsWithElements;
|
||||
|
||||
public $novaPageUrl;
|
||||
|
||||
public $queryParams;
|
||||
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($path = '/')
|
||||
{
|
||||
$this->setNovaPage($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL for the page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
if ($this->queryParams) {
|
||||
return $this->novaPageUrl.'?'.http_build_query($this->queryParams);
|
||||
}
|
||||
|
||||
return $this->novaPageUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert page not found.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assertOk(Browser $browser)
|
||||
{
|
||||
$browser->waitForLocation($this->novaPageUrl)
|
||||
->assertPathIs($this->novaPageUrl)
|
||||
->waitFor('@nova-content');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert page not found.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assertNotFound(Browser $browser)
|
||||
{
|
||||
$browser->on(new NotFound());
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert page not forbidden.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assertForbidden(Browser $browser)
|
||||
{
|
||||
$browser->on(new Forbidden());
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert page doesn't contain breadcrumb.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assertWithoutBreadcrumb(Browser $browser)
|
||||
{
|
||||
$browser->assertMissing('@breadcrumbs');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set luxon timezone for the frontend.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $timezone
|
||||
* @return void
|
||||
*/
|
||||
public function luxonTimezone(Browser $browser, string $timezone = 'system')
|
||||
{
|
||||
$browser->script('Nova.$testing.timezone("'.$timezone.'")');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the global element shortcuts for the site.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function siteElements(): array
|
||||
{
|
||||
return [
|
||||
'@nova-content' => '[dusk="content"]',
|
||||
'@nova-form' => '[dusk="content"]',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Nova Page URL.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
protected function setNovaPage(string $path)
|
||||
{
|
||||
$this->novaPageUrl = Nova::path().'/'.trim($path, '/');
|
||||
}
|
||||
}
|
||||
25
nova/src/Testing/Browser/Pages/Replicate.php
Normal file
25
nova/src/Testing/Browser/Pages/Replicate.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
class Replicate extends Create
|
||||
{
|
||||
public $fromResourceId;
|
||||
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param int|string $fromResourceId
|
||||
* @param array $queryParams
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($resourceName, $fromResourceId, $queryParams = [])
|
||||
{
|
||||
parent::__construct($resourceName, $queryParams);
|
||||
|
||||
$this->fromResourceId = $fromResourceId;
|
||||
|
||||
$this->setNovaPage("/resources/{$this->resourceName}/{$this->fromResourceId}/replicate");
|
||||
}
|
||||
}
|
||||
111
nova/src/Testing/Browser/Pages/Update.php
Executable file
111
nova/src/Testing/Browser/Pages/Update.php
Executable file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Laravel\Nova\Testing\Browser\Components\Modals\CreateRelationModalComponent;
|
||||
|
||||
class Update extends Page
|
||||
{
|
||||
use InteractsWithRelations;
|
||||
|
||||
public $resourceName;
|
||||
|
||||
public $resourceId;
|
||||
|
||||
public $queryParams;
|
||||
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param int $resourceId
|
||||
* @param array $queryParams
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($resourceName, $resourceId, $queryParams = [])
|
||||
{
|
||||
$this->resourceName = $resourceName;
|
||||
$this->resourceId = $resourceId;
|
||||
$this->queryParams = $queryParams;
|
||||
|
||||
$this->setNovaPage("/resources/{$this->resourceName}/{$this->resourceId}/edit");
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the inline create relation.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @param string $uriKey
|
||||
* @param callable $fieldCallback
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function runInlineCreate(Browser $browser, $uriKey, callable $fieldCallback)
|
||||
{
|
||||
$browser->whenAvailable("@{$uriKey}-inline-create", function ($browser) use ($fieldCallback) {
|
||||
$browser->click('')
|
||||
->elsewhereWhenAvailable(new CreateRelationModalComponent(), function ($browser) use ($fieldCallback) {
|
||||
$fieldCallback($browser);
|
||||
|
||||
$browser->confirm()->pause(250);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the update button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function update(Browser $browser)
|
||||
{
|
||||
$browser->dismissToasted()
|
||||
->waitFor('@update-button')
|
||||
->click('@update-button')
|
||||
->pause(500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the update and continue editing button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function updateAndContinueEditing(Browser $browser)
|
||||
{
|
||||
$browser->dismissToasted()
|
||||
->waitFor('@update-and-continue-editing-button')
|
||||
->click('@update-and-continue-editing-button')
|
||||
->pause(500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the cancel button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(Browser $browser)
|
||||
{
|
||||
$browser->dismissToasted()
|
||||
->click('@cancel-update-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertOk()->waitFor('@nova-form');
|
||||
}
|
||||
}
|
||||
139
nova/src/Testing/Browser/Pages/UpdateAttached.php
Executable file
139
nova/src/Testing/Browser/Pages/UpdateAttached.php
Executable file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
class UpdateAttached extends Page
|
||||
{
|
||||
public $resourceName;
|
||||
|
||||
public $resourceId;
|
||||
|
||||
public $relation;
|
||||
|
||||
public $relatedId;
|
||||
|
||||
public $viaRelationship;
|
||||
|
||||
public $viaPivotId;
|
||||
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param string $resourceId
|
||||
* @param string $relation
|
||||
* @param string $relatedId
|
||||
* @param string|null $viaRelationship
|
||||
* @param string|null $viaPivotId
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($resourceName, $resourceId, $relation, $relatedId, $viaRelationship = null, $viaPivotId = null)
|
||||
{
|
||||
$this->relation = $relation;
|
||||
$this->relatedId = $relatedId;
|
||||
$this->resourceId = $resourceId;
|
||||
$this->resourceName = $resourceName;
|
||||
$this->viaRelationship = $viaRelationship;
|
||||
$this->viaPivotId = $viaPivotId;
|
||||
|
||||
$this->setNovaPage("/resources/{$this->resourceName}/{$this->resourceId}/edit-attached/{$this->relation}/{$this->relatedId}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new page instance for Belongs-to-Many.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param string $resourceId
|
||||
* @param string $relation
|
||||
* @param string $relatedId
|
||||
* @param string|null $viaRelationship
|
||||
* @param string|null $viaPivotId
|
||||
* @return static
|
||||
*/
|
||||
public static function belongsToMany($resourceName, $resourceId, $relation, $relatedId, $viaRelationship = null, $viaPivotId = null)
|
||||
{
|
||||
return new static($resourceName, $resourceId, $relation, $relatedId, $viaRelationship, $viaPivotId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new page instance for Morph-to-Many.
|
||||
*
|
||||
* @param string $resourceName
|
||||
* @param string $resourceId
|
||||
* @param string $relation
|
||||
* @param string $relatedId
|
||||
* @param string|null $viaRelationship
|
||||
* @param string|null $viaPivotId
|
||||
* @return static
|
||||
*/
|
||||
public static function morphToMany($resourceName, $resourceId, $relation, $relatedId, $viaRelationship = null, $viaPivotId = null)
|
||||
{
|
||||
return new static($resourceName, $resourceId, $relation, $relatedId, $viaRelationship, $viaPivotId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL for the page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return $this->novaPageUrl.'?'.http_build_query(array_filter([
|
||||
'viaRelationship' => $this->viaRelationship ?? $this->relation,
|
||||
'viaPivotId' => $this->viaPivotId,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the update button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function update(Browser $browser)
|
||||
{
|
||||
$browser->dismissToasted()
|
||||
->click('@update-button')
|
||||
->pause(750);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the update and continue editing button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function updateAndContinueEditing(Browser $browser)
|
||||
{
|
||||
$browser->dismissToasted()
|
||||
->click('@update-and-continue-editing-button')
|
||||
->pause(750);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the cancel button.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(Browser $browser)
|
||||
{
|
||||
$browser->dismissToasted()
|
||||
->click('@cancel-update-attached-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertOk()->waitFor('@nova-form');
|
||||
}
|
||||
}
|
||||
17
nova/src/Testing/Browser/Pages/UserIndex.php
Executable file
17
nova/src/Testing/Browser/Pages/UserIndex.php
Executable file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Browser\Pages;
|
||||
|
||||
class UserIndex extends Index
|
||||
{
|
||||
/**
|
||||
* Create a new page instance.
|
||||
*
|
||||
* @param array $queryParams
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($queryParams = [])
|
||||
{
|
||||
parent::__construct('users', $queryParams);
|
||||
}
|
||||
}
|
||||
22
nova/src/Testing/Concerns/MakesHttpRequests.php
Normal file
22
nova/src/Testing/Concerns/MakesHttpRequests.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Testing\Concerns;
|
||||
|
||||
use Illuminate\Foundation\Testing\Concerns\MakesHttpRequests as IlluminateMakesHttpRequests;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
trait MakesHttpRequests
|
||||
{
|
||||
use IlluminateMakesHttpRequests;
|
||||
|
||||
/**
|
||||
* Create the request instance used for testing from the given Symfony request.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $symfonyRequest
|
||||
* @return \Laravel\Nova\Http\Requests\NovaRequest
|
||||
*/
|
||||
protected function createTestRequest($symfonyRequest)
|
||||
{
|
||||
return NovaRequest::createFromBase($symfonyRequest);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user