drupalextension icon indicating copy to clipboard operation
drupalextension copied to clipboard

Big pipe compatibility follow-up

Open zaporylie opened this issue 8 years ago • 21 comments

#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: https://github.com/jhedstrom/drupalextension/issues/258#issuecomment-193357483)

zaporylie avatar Nov 15 '16 20:11 zaporylie


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 avatar Nov 15 '16 21:11 zaporylie

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?

zaporylie avatar Nov 15 '16 21:11 zaporylie

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

mglaman avatar Mar 20 '17 01:03 mglaman

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!

jhedstrom avatar Dec 05 '17 18:12 jhedstrom

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.

Berdir avatar Dec 05 '17 23:12 Berdir

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...

jhedstrom avatar Dec 06 '17 17:12 jhedstrom

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.

Berdir avatar Dec 06 '17 17:12 Berdir

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.

wimleers avatar Dec 06 '17 18:12 wimleers

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

jhedstrom avatar Dec 12 '17 19:12 jhedstrom

I opened https://github.com/FriendsOfPHP/Goutte/issues/329 for the Goutte browser.

jhedstrom avatar Dec 12 '17 19:12 jhedstrom

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 avatar Dec 12 '17 21:12 jhedstrom

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.

davereid avatar Jul 13 '18 15:07 davereid

After applying the patch it solved a pretty mean issue for me. https://github.com/jhedstrom/drupalextension/issues/258#issuecomment-448001156

normanlolx avatar Dec 17 '18 21:12 normanlolx

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.

jhedstrom avatar Dec 17 '18 23:12 jhedstrom

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.

normanlolx avatar Dec 27 '18 22:12 normanlolx

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.

vever001 avatar Oct 23 '20 17:10 vever001

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

bsuttis avatar Mar 15 '21 21:03 bsuttis

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.
    }
  }

}

vever001 avatar Mar 15 '21 22:03 vever001

@vever001 thanks, it's working!

bsuttis avatar Mar 16 '21 00:03 bsuttis

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.

https://github.com/jhedstrom/drupalextension/pull/325#issuecomment-799804471 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 avatar Mar 19 '21 17:03 FlorentTorregrosa

Hello,

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

Waiting for the PR to be merged when possible.

FlorentTorregrosa avatar Mar 23 '21 10:03 FlorentTorregrosa