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

Big pipe compatibility follow-up #325

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

zaporylie
Copy link

#259 doesn't test messages for authenticated users. This follow-up PR should prove that messages work only for anonymous users.

In next commits to branch I will suggest how can we fix it (based on workaround proposed here: #258 (comment))

@zaporylie
Copy link
Author


The command "vendor/bin/behat -fprogress --strict" exited with 1.
103.19s$ vendor/bin/behat -fprogress --profile=drupal${DRUPAL_VERSION} --strict
...................................................................... 70
...................................................................... 140
...................................................................... 210
.............F.....F

--- Failed steps:
    Then I should see the message "The configuration options have been saved." # features/messages.feature:27
      The page 'http://127.0.0.1:8888/admin/config/development/maintenance?q=admin/config/development/maintenance' does not contain any messages (Exception)
    Then I should see the message "The configuration options have been saved." # features/messages.feature:36
      The page 'http://127.0.0.1:8888/admin/config/development/maintenance?q=admin/config/development/maintenance' does not contain any messages (Exception)

44 scenarios (42 passed, 2 failed)
230 steps (228 passed, 2 failed)
1m42.51s (94.91Mb)
The command "vendor/bin/behat -fprogress --profile=drupal${DRUPAL_VERSION} --strict" exited with 1.
0.00s$ test ${DRUPAL_VERSION} -ne 7 || vendor/bin/behat -fprogress --profile=drush --strict

Extra test scenarios proved DrupalExtension doesn't work well for Authenticated user and BigPipe enabled.

In next commit I will suggest how can we fix it.

@zaporylie
Copy link
Author

The command "vendor/bin/behat -fprogress --strict" exited with 1.
92.04s$ vendor/bin/behat -fprogress --profile=drupal${DRUPAL_VERSION} --strict
...................................................................... 70
...................................................................... 140
...................................................................... 210
..................F

--- Failed steps:
    Then I should see the message "The configuration options have been saved." # features/messages.feature:35
      The page 'http://127.0.0.1:8888/admin/config/development/maintenance?q=admin/config/development/maintenance' does not contain any messages (Exception)

44 scenarios (43 passed, 1 failed)
229 steps (228 passed, 1 failed)
1m31.47s (95.28Mb)

As you can see first failing step (Non-JS messages for authenticated) has been fixed.

In the same time extra scenarios have revealed that [email protected] doesn't work well with BigPipe. I tested that scenario locally with PhantomJS and it works perfect. Did you consider switching from zombiejs to phantomjs?

@mglaman
Copy link

mglaman commented Mar 20, 2017

I copied the BigPipeContext into my project and it solved my woes. My project also uses PhantomJS vs zombiejs

@jhedstrom jhedstrom changed the title Followup to #259 Big pipe compatibility follow-up Dec 5, 2017
@jhedstrom
Copy link
Owner

Sorry for the long delay in getting to this. It looks like a great start! It needs to be rebased/merged with the latest master, and from the looks of it, there were some JS failures too. Thanks for working on this!

@Berdir
Copy link
Contributor

Berdir commented Dec 5, 2017

Is there no official way to check if a driver supports JS or not?

Using a try/catch for that is not exactly a clean way. Also wondering if this really should be an optional context, everyone will have to figure out then that this exists and add it to this project, should at least be documented then somehere.

I'll also ping Wim Leers about this.

@jhedstrom
Copy link
Owner

jhedstrom commented Dec 6, 2017

Is there no official way to check if a driver supports JS or not?

From what I can tell, no. The JS drivers don't implement any additional interfaces or anything to differentiate themselves from the non-JS drivers...

@Berdir
Copy link
Contributor

Berdir commented Dec 6, 2017

That's pretty unfortunate then, in my project I could obviously just check the actual driver class since I know what it is.

Could we maybe somehow store this on a property or so so we don't have to throw and catch an exception for every single scenario? I guess it won't make a measurable difference

The thing is that big pipe should be compatible with non-JS clients by redirecting them through a meta tag and then sets that cookie itself IIRC. But it looks like the driver doesn't support that.

@wimleers
Copy link

wimleers commented Dec 6, 2017

Is there no official way to check if a driver supports JS or not?

That'd be great!

But I think catching UnsupportedDriverActionException and then setting the no-JS cookie is a pretty clever hack.

The thing is that big pipe should be compatible with non-JS clients by redirecting them through a meta tag and then sets that cookie itself IIRC. But it looks like the driver doesn't support that.

Correct. But if the driver doesn't support that, then it's violating one of the foundational features of web browsers: it doesn't respect <noscript><meta http-equiv="Refresh" content="0; URL=http://example.com/somewhere"></noscript>. Which means that this driver doesn't support graceful degradation for non-JS clients. Which sounds like a huge oversight.


Finally: when does Behat run the assertions? Does it wait for the load event to complete? I'm asking because otherwise tests using BigPipe could run into random failures depending on how fast the server responded, and depending on how fast the JS was executed.

@jhedstrom
Copy link
Owner

I've merged the latest master for this over in #445.

@jhedstrom
Copy link
Owner

I opened FriendsOfPHP/Goutte#329 for the Goutte browser.

@jhedstrom
Copy link
Owner

In local testing, it would appear that the attempt to just set the cookie in a @BeforeScenario hook won't work, since when a user logs in, they get a new session that loses this cookie for some reason.

@jhedstrom jhedstrom reopened this Dec 12, 2017
fabpot added a commit to symfony/symfony that referenced this pull request May 18, 2018
This PR was squashed before being merged into the 4.2-dev branch (closes #27118).

Discussion
----------

[BrowserKit] Adds support for meta refresh

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #27117    <!-- #-prefixed issue number(s), if any -->
| License       | MIT
| Doc PR        | symfony/symfony-docs#... <!-- required for new features -->

This adds support for following redirects defined by the `http-equiv=refresh` meta tag, such as

```
<meta http-equiv="Refresh" content="0; URL=http://example.com/somewhere">
```
Additional background at jhedstrom/drupalextension#325 (comment)
<!--
Write a short README entry for your feature/bugfix here (replace this comment block.)
This will help people understand your PR and can be used as a start of the Doc PR.
Additionally:
 - Bug fixes must be submitted against the lowest branch where they apply
   (lowest branches are regularly merged to upper ones so they get the fixes too).
 - Features and deprecations must be submitted against the master branch.
-->

Commits
-------

1c64c82 [BrowserKit] Adds support for meta refresh
@davereid
Copy link

We are definitely experiencing this a lot recently:

Finally: when does Behat run the assertions? Does it wait for the load event to complete? I'm asking because otherwise tests using BigPipe could run into random failures depending on how fast the server responded, and depending on how fast the JS was executed.

@leymannx
Copy link

After applying the patch it solved a pretty mean issue for me. #258 (comment)

@jhedstrom
Copy link
Owner

Previously this didn't seem to resolve the issue (see my comments above regarding losing cookies on login), but if it's working for others, and we can get the tests passing, I'm all for this workaround until the fix in browserkit above makes its way into Mink, etc.

@leymannx
Copy link

Worth mentioning the patch results in an exception to be thrown on @api tagged scenarios when the BigPipe module is not enabled.

  ┌─ @BeforeScenario # Drupal\DrupalExtension\Context\BigPipeContext::prepareBigPipeNoJsCookie()

  ╳  Fatal error: Class 'Drupal\big_pipe\Render\Placeholder\BigPipeStrategy' not found (Behat\Testwork\Call\Exception\FatalThrowableError)

I'm actually quite surprised by that behavior. How smart this extension is that it won't load the class of a disabled module?!

After re-enabling BigPipe it works just fine again.

@jhedstrom jhedstrom modified the milestones: 4.0 release, 4.1 release Jul 23, 2019
*
* @BeforeScenario
*/
public function prepareBigPipeNoJsCookie()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did have something like this in a custom project, but it stopped working with behat-extension 4, due to the authentication manager. That now does a fast logout unconditionally before login which kills the session and with that, the cookie.

I actually already did the same in my overriden logout() method with drupal-extension 3 but I thn also re-set the cookie there.

I switched to an @afterstep and adding the cookie if I have a user and the cookie isn't there yet, but that doesn't seem like a very efficient approach.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can solve it by emitting an event when we do the fast logout in the authentication manager?

@vever001
Copy link

Thanks for this example @Berdir
On my side, using v4.0.1 and v4.1.0 it didn't work with a BeforeScenario.
I have overridden the login method and set the cookie there, which seems to work for now.

@bsuttis
Copy link

bsuttis commented Mar 15, 2021

@vever001 can you post how you overrode the login method?

@vever001
Copy link

vever001 commented Mar 15, 2021

Sure, this is the context I added to the behat.ymlin default.suites.default.contexts section:

<?php

declare(strict_types = 1);

namespace Drupal\Tests\my_namespace\Behat;

use Behat\Mink\Exception\UnsupportedDriverActionException;
use Drupal\big_pipe\Render\Placeholder\BigPipeStrategy;
use Drupal\DrupalExtension\Context\DrupalContext as DrupalExtensionDrupalContext;

/**
 * Provides step definitions for interacting with Drupal.
 */
class DrupalContext extends DrupalExtensionDrupalContext {

  /**
   * {@inheritdoc}
   */
  public function login(\stdClass $user) {
    parent::login($user);
    $this->disableBigPipe();
  }

  /**
   * Disables Big Pipe.
   *
   * Workaround for issue with drupalextension and big_pipe.
   * See https://github.com/jhedstrom/drupalextension/issues/258
   */
  protected function disableBigPipe() {
    try {
      // Check if JavaScript can be executed by Driver.
      $this->getSession()->getDriver()->executeScript('true');
    }
    catch (UnsupportedDriverActionException $e) {
      // Set NOJS cookie.
      $this
        ->getSession()
        ->setCookie(BigPipeStrategy::NOJS_COOKIE, TRUE);
    }
    catch (\Exception $e) {
      // Mute exceptions.
    }
  }

}

@bsuttis
Copy link

bsuttis commented Mar 16, 2021

@vever001 thanks, it's working!

@FlorentTorregrosa
Copy link
Contributor

FlorentTorregrosa commented Mar 19, 2021

Hello,

Edit:

  • drupal/drupal-extension: 4.1.0
  • drupal/core-recommended: 9.1.5
  • drupal/core-dev: 9.1.5

I am writting (my almost first) Behat tests on a comment form for anonymous users and I wanted to test that after submitting the form, the approbation message is displayed and the admin receives an email.

So I encountered this issue.

I have not tested the code of this PR yet.

#325 (comment) is not working for me because in my case, I am with an anonymous user. So I guess the @BeforeScenario of the conext in the PR will be better.

And I have another problem, if I write a context in a module, either in src or tests/src with proper namespace then referencing it in my behat.yml, the context is not detected. Is there something special to do?

I find out that for example Search API has a search_api.behat.inc file but I would really like to avoid .inc files. And no problem for a custom context inside a features/bootstrap folder from wher the behat.yml file is located.

I can't find anything about that in the documentation.

Thanks for any help.

@FlorentTorregrosa
Copy link
Contributor

Hello,

I add manually tested the new context. It fixed my usage. Thanks!

Waiting for the PR to be merged when possible.

{
try {
// Check if JavaScript can be executed by Driver.
$this->getSession()->getDriver()->executeScript('true');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were using a similar approach (https://github.com/drupaltest/behat-traits/blob/8.x-1.x/src/Traits/BrowserCapabilityDetectionTrait.php#L42) but this doesn't work with ChromeDriver which throws a fatal error when no page has been loaded yet (which is the case when running @BeforeScenario)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.