How to override env variables in Laravel Dusk

主宰稳场 提交于 2019-12-29 02:09:15

问题


Unfortunately config(['key' => 'newValue']) doesn't work in a Dusk setup (for overriding a config value), presumably because it would change the config of the system running the test rather than the experience of the headless browser that gets opened to execute the flow.

And sometimes I can see no way around needing to temporarily change an env value for a certain Dusk test.

E.g. temporarily set QUEUE_DRIVER=sync when usually it is 'dusk-connection', but in one particular test, I need to check for values in the 'jobs' tables in the DB.

Before upgrading to Laravel >=5.8 (and therefore newer versions of DotEnv), I was able to use this function called within a Dusk test before $this->browse(...:

/**
 * Overrides any .env variables for Dusk tests. https://laracasts.com/discuss/channels/testing/how-to-change-env-variable-config-in-dusk-test 
 * The changes exist only for that one test because of tearDown.
 * Remember that you need to be using `php artisan dusk` instead of `phpunit`.
 * https://stackoverflow.com/questions/54407784/laravel-dusk-how-to-change-config-values-before-each-test-for-the-browser#comment103224655_54407784
 *
 * @param array $variables
 */
protected function overrideDuskEnv($variables = []) {
    $path = self::DOT_ENV;
    if (file_exists($path)) {
        $contentToPrepend = '';
        foreach ($variables as $key => $value) {// Convert all new parameters to expected format
            $contentToPrepend .= $key . '="' . $value . '"' . PHP_EOL;
        }
        $originalFileContents = $this->envContents;
        $comment = '# ==============================================' . PHP_EOL . '# VARIABLES ABOVE THIS LINE are from "' . __FUNCTION__ . '" function in DuskTestCase ( https://laracasts.com/discuss/channels/testing/how-to-change-env-variable-config-in-dusk-test )' . PHP_EOL;
        file_put_contents($path, $contentToPrepend . $comment . $originalFileContents); //"If they are appended, it doesn't seem to take priority."
    } else {
        throw new \Exception('Could not find env file to override!');
    }
}

I was able to call it like this: $this->overrideDuskEnv(['QUEUE_DRIVER' => 'sync']);

But in more recent Laravel versions, environment variables are immutable (see "Read-Only env Helper").

How can I achieve my goal, where Dusk uses .env.dusk.local for most tests but then for certain tests may differ slightly?


回答1:


Finally after struggling with this problem for 10+ hours, I have a solution.

/**
 * @param array $variables
 */
protected function overrideDuskEnv($variables = []) {
    $path = self::DOT_ENV;
    if (file_exists($path)) {
        $contentToAppend = '';
        foreach ($variables as $key => $value) {// Convert all new parameters to expected format
            $contentToAppend .= $key . '="' . $value . '"' . PHP_EOL;
        }
        $originalFileContents = $this->envContents;
        $comment = '# ==============================================' . PHP_EOL . '# VARIABLES BELOW THIS LINE are from "' . __FUNCTION__ . '" function in DuskTestCase ( https://laracasts.com/discuss/channels/testing/how-to-change-env-variable-config-in-dusk-test )' . PHP_EOL;
        $this->baseCommand->consoleOutput('Appending to ' . $path . ': ' . $contentToAppend);
        file_put_contents($path, $originalFileContents . $comment . $contentToAppend); //It used to be the case that "If they are appended [rather than prepended], it doesn't seem to take priority", but after the DotEnv upgrade in Laravel 5.8, it seems prepending doesn't work and appending does.
    } else {
        throw new \Exception('Could not find env file to override!');
    }
}

Then in my setUp() function in my Dusk test class, I call:

    $this->overrideDuskEnv([
        'SIGNUP_FORM_POST_PATH' => \App\Helpers\Routes::SIGNUP,
        'QUEUE_DRIVER' => \App\Helpers\ConfigConstants::DUSK_CONNECTION
    ]);

Then in each test function after the closing of $this->browse(function (Browser $browser)... and before assertions, I call:

config(['queue.default' => \App\Helpers\ConfigConstants::DUSK_CONNECTION]); //this does not affect the headless browser but IS probably necessary here so that assertQueued knows to pull from the queue that the headless browser was using.

The tricky part to understand with Dusk is that the environment variables (and therefore the config arrays) of the console process running the tests differ from those that get used by the headless browser (simulating what a real user would experience).

By the way, I had been so hopeful about approaches like this one, but they turned out to be complete wastes of time because DuskCommand is already calling overload to make the env variables mutable.



来源:https://stackoverflow.com/questions/58450836/how-to-override-env-variables-in-laravel-dusk

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!