lucatume / wp-browser

The easy and reliable way to test WordPress with Codeception. 10 years of proven success.
https://wpbrowser.wptestkit.dev/
MIT License
603 stars 86 forks source link

[BUG] WordPress not loaded with WPLoader loadOnly: true #744

Closed lxbdr closed 2 months ago

lxbdr commented 3 months ago

Version 3.5
If you're opening an issue to report a breakage caused by version 3.5; please read the migration guide first first!

Environment OS: Linux PHP version: 8.2 Installed Codeception version: 5.1.2 Installed wp-browser version: 4.2.5 WordPress version: 6.6 Local development environment: VVV (Vagrant) WordPress structure and management: default

Can you perform the test manually? If applicable, try to walk through the test and execute it manually: can you do it using the browser?

Codeception configuration file
Paste, in a fenced YAML block, the content of your Codeception configuration file; remove any sensitive data!

namespace: Tests
support_namespace: Support
paths:
    tests: tests
    output: tests/_output
    data: tests/Support/Data
    support: tests/Support
    envs: tests/_envs
actor_suffix: Tester
params:
    - tests/.env
extensions:
    enabled:
        - Codeception\Extension\RunFailed

Suite configuration file Paste, in a fenced YAML block, the content of the suite configuration file; remove any sensitive data!

# Integration suite configuration
#
# Run integration and "WordPress unit" tests.

actor: EndToEndTester
bootstrap: _bootstrap.php
modules:
    enabled:
        - lucatume\WPBrowser\Module\WPBrowser
#        - lucatume\WPBrowser\Module\WPWebDriver
        - lucatume\WPBrowser\Module\WPDb
        - lucatume\WPBrowser\Module\WPFilesystem
        - lucatume\WPBrowser\Module\WPLoader
#        - lucatume\WPBrowser\Module\WPCLI
    config:
        lucatume\WPBrowser\Module\WPBrowser:
          url: '%WORDPRESS_URL%'
          adminUsername: '%WORDPRESS_ADMIN_USER%'
          adminPassword: '%WORDPRESS_ADMIN_PASSWORD%'
          adminPath: '%WORDPRESS_ADMIN_PATH%'
        lucatume\WPBrowser\Module\WPWebDriver:
            url: '%WORDPRESS_URL%'
            adminUsername: '%WORDPRESS_ADMIN_USER%'
            adminPassword: '%WORDPRESS_ADMIN_PASSWORD%'
            adminPath: '%WORDPRESS_ADMIN_PATH%'
            browser: chrome
            host: '%CHROMEDRIVER_HOST%'
            port: '%CHROMEDRIVER_PORT%'
            path: '/'
            window_size: 1200x1000
            capabilities:
              "goog:chromeOptions":
                args:
                  - "--headless"
                  - "--disable-gpu"
                  - "--disable-dev-shm-usage"
                  - "--proxy-server='direct://'"
                  - "--proxy-bypass-list=*"
                  - "--no-sandbox"
        lucatume\WPBrowser\Module\WPDb:
            dbUrl: '%WORDPRESS_DB_URL%'
#            dump: 'tests/Support/Data/dump.sql'
            populate: false
            cleanup: false
#            reconnect: false
#            createIfNotExists: false
            url: '%WORDPRESS_URL%'
            urlReplacement: false
            domain: '%WORDPRESS_DOMAIN%'
            tablePrefix: '%WORDPRESS_TABLE_PREFIX%'
        lucatume\WPBrowser\Module\WPFilesystem:
            wpRootFolder: '%WORDPRESS_ROOT_DIR%'
        lucatume\WPBrowser\Module\WPLoader:
            loadOnly: true
            wpRootFolder: '%WORDPRESS_ROOT_DIR%'
            dbUrl: '%WORDPRESS_DB_URL%'
            domain: '%WORDPRESS_DOMAIN%'
#            tablePrefix: '%WORDPRESS_TABLE_PREFIX%'
        lucatume\WPBrowser\Module\WPCLI:
          path: '%WORDPRESS_ROOT_DIR%'
          throw: true

Describe the bug I would like to run End to End tests on the existing installation without loading a dump. When setting no dump, populate: false and cleanup: false, WordPress is not loaded and not available in the tests. I ran the test using php8.2 vendor/bin/codecept run EndToEnd --debug.

I stepped through the code and suspect the following issue: In WPLoader::_initialize the loadWordPress call is hooked into Events::SUITE_BEFORE

        if (!empty($config['loadOnly'])) {
            $this->checkInstallationToLoadOnly();
            $this->debug('The WordPress installation will be loaded after all other modules have been initialized.');

            Dispatcher::addListener(Events::SUITE_BEFORE, function (): void {
                $this->loadWordPress(true);
            });

            return;
        }

When Codeception\SuiteManager dispatches Events::SUITE_BEFORE the listener is not being called. When checking, the closure is not in the listeners array. I suspect the listener is not correctly added.

Output

Codeception PHP Testing Framework v5.1.2 https://stand-with-ukraine.pp.ua

  [Connecting To Db] {"config":{"tablePrefix":"wp_","populate":false,"cleanup":false,"reconnect":false,"dump":[],"populator":"","urlReplacement":false,"originalUrl":"","waitlock":10,"createIfNotExists":false,"dbUrl":"mysql://wp:wp@localhost:3306/lw-partner","url":"http://lw-partner.test","domain":"lw-partner.test","dsn":"mysql:host=localhost;port=3306;dbname=lw-partner","user":"wp","password":"wp"},"options":[]}
  [Db] Connected to default lw
  The WordPress installation will be loaded after all other modules have been initialized.

Tests.EndToEnd Tests (3) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Modules: \lucatume\WPBrowser\Module\WPBrowser, \lucatume\WPBrowser\Module\WPDb, \lucatume\WPBrowser\Module\WPFilesystem, \lucatume\WPBrowser\Module\WPLoader
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AccessControlCest: Test something
Signature: Tests\EndToEnd\AccessControlCest:testSomething
Test: tests/EndToEnd/AccessControlCest.php:testSomething
Scenario --
 ERROR 

There was 1 error:
1) AccessControlCest: Test something
 Test  tests/EndToEnd/AccessControlCest.php:testSomething

  [Error] Class "WP_User" not found  

#1  /srv/www/lw-partner/public_html/wp-content/themes/leowittwer/tests/EndToEnd/AccessControlCest.php:24
#2  Tests\EndToEnd\AccessControlCest->testSomething
#3  /srv/www/lw-partner/public_html/wp-content/themes/leowittwer/vendor/bin/codecept:119

ERRORS!
Tests: 3, Assertions: 1, Errors: 1.
  [Db] Disconnected from default

To Reproduce Steps to reproduce the behavior.

Expected behavior A clear and concise description of what you expected to happen.

Screenshots If applicable, add screenshots to help explain your problem.

Additional context Add any other context about the problem here.

lxbdr commented 3 months ago

Adding this to WPLoader seems to fix the problem:

    public function _beforeSuite( array $settings = [] ) {
        parent::_beforeSuite( $settings );
        Dispatcher::dispatch( Events::SUITE_BEFORE, $this );
    }
lucatume commented 3 months ago

Thanks @lxbdr for reporting and investigating the issue.

I will try to reproduce the issue next week, debug it and fix it.

I might reach out for help should I not be able to reproduce.

When Codeception\SuiteManager dispatches Events::SUITE_BEFORE the listener is not being called. When checking, the closure is not in the listeners array. I suspect the listener is not correctly added.

Good research, thanks. The projects "wraps" the Codeception event dispatcher to dispatch and subscribe default and custom events. Looking at the extensions section of your configuration file I can see you're not using the EventDispatcherBridge extension: that might be causing the connection not to happen correctly. Could you try adding the extension and removing the code from the WPLoader module class? Even if it runs correctly this way, the module logic could be improved and fixed.

lxbdr commented 3 months ago

Thanks for taking a look at this. I have just tested adding the EventDispatcherBridge to extensions and it seems to work. Maybe this could be added to the getting started docs or throw an exception if the extension is not loaded

lucatume commented 3 months ago

Thanks @lxbdr for the confirmation of my suspect.

Maybe this could be added to the getting started docs or throw an exception if the extension is not loaded. Yes, if the extensions turns out to be really required. Ideally, and I still have to take the time to make sure it's possible, I would like to avoid making an extension, optional by nature, required.

I will look into this and update this issue accordingly.

sanjucta commented 2 months ago

@lucatume Hey! We have the same issue and @lxbdr 's suggestion fixes it for us! Is this going to be merged anytime soon?