Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add waitForEvent() method #972

Merged
merged 3 commits into from
Apr 11, 2022
Merged

Add waitForEvent() method #972

merged 3 commits into from
Apr 11, 2022

Conversation

michaelhue
Copy link
Contributor

This pull requests adds a waitForEvent() method to the WaitsForElements trait, making it available to the Browser class.

It also adds a corresponding test case to WaitsForElementsTest.

Explanation

waitForEvent(
    string $type,
    ?string $target = null,
    ?int $seconds = null
): self

The waitForEvent() method pauses the test execution until a given event type occurs on a target element or object.

This is especially useful when working with front-end libraries like InertiaJS or Hotwire/Turbo, since those libraries will trigger events that can be very helpful for automated testing. For example, clicking a link and waiting for the inertia:navigate event before continuing with the test.

Usage examples

Waiting for events on DOM elements:

// Targeting the body element
$browser->waitForEvent('load');

// Targeting CSS selectors
$browser->waitForEvent('load', 'img');

// Targeting scoped selectors
$browser->with('img', function ($img) {
	$img->waitForEvent('load');
});

// Targeting dusk selectors
$browser->waitForEvent('load', '@dusk-selector');

Waiting for events on document or window:

$browser->waitForEvent('scroll', 'document');
$browser->waitForEvent('resize', 'window');

Waiting for InertiaJS events:

$browser->visit('/login')
	->waitForEvent('inertia:navigate', 'document');
	
$browser->press('Submit')
	->waitForEvent('inertia:finish', 'document');

Waiting for events with a custom timeout in seconds:

$browser->waitForEvent('load', 'img.huge-image', 10);

Discussion

I’m very open to suggestions on how to improve this. A few thoughts:

I’m not huge fan of the $target argument being either a selector or 'document' / 'window', since it’s not very clearly communicated. Adding a description for $target in the docblock could help, but that would be inconsistent with the rest of the Dusk codebase.

I also thought about adding different methods for differentiation:

waitForEvent(string $type, ?string $selector = null);
// or…
waitForElementEvent(string $type, ?string $selector = null);

// …and…
waitForDocumentEvent(string $type);
waitForWindowEvent(string $type);

But in the end I opted for a single method, since I felt it still had the best developer ergonomics.

I see potential for more convenience methods using events, for example:

  • visitAndWaitForEvent()
  • visitRouteAndWaitForEvent()
  • clickLinkAndWaitForEvent()
  • pressAndWaitForEvent()

Should these methods be desirable in the future, maybe a dedicated WaitsForEvents or InteractsWithEvents trait would be good.

Finally I’m unsure about using eval() in the executeAsyncScript() call. But I like that it makes the JavaScript code very concise since it works with object names (document/window) and element references at the same time. Also in a testing environment, I feel eval() is not that dramatic. Maybe it could lead to problems with content security policies, I’m not sure how Dusk/WebDriver handles those.

This commit adds a `waitForEvent()` method to the `WaitsForElements`
trait, making it available to the `Browser` class.

The `waitForEvent()` method pauses the test execution until a given
event `type` occurs on a `target` element or object.

It also adds a corresponding test case to `WaitsForElementsTest`.
@taylorotwell taylorotwell merged commit 98901d4 into laravel:6.x Apr 11, 2022
@taylorotwell
Copy link
Member

Can you submit a docs PR to laravel/docs?

@michaelhue michaelhue deleted the wait-for-event branch April 11, 2022 18:55
@michaelhue
Copy link
Contributor Author

Sure!

Thanks for the merge Taylor!

taylorotwell added a commit to laravel/docs that referenced this pull request Apr 12, 2022
* Add docs for `waitForEvent` method

Adds a section to the Dusk documentation describing the new
`waitForEvent` method added in laravel/dusk#972.

* formatting

Co-authored-by: Taylor Otwell <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants