Codeception\Module\Yii2 can't open external URL though can be opened by browser

Created on 30 Dec 2016  Â·  15Comments  Â·  Source: Codeception/Codeception

What are you trying to achieve?

I'm trying to get my REST endpoint working. The following url gets 200 response in REST clients.

http://sign-up-api.local/v1/user/info

What do you get instead?

I'm getting this exception.

CodeceptionModuleYii2 can't open external URL

Provide console output if related. Use -vvv mode for more details.

➜  src git:(master) ✗ composer exec codecept run -vvv api                                                                                                                     <<<
Reading ./composer.json
Loading config file /Users/seng/.composer/config.json
Loading config file /Users/seng/.composer/auth.json
Loading config file ./composer.json
Checked CA file /private/etc/ssl/cert.pem: valid
Executing command (/Users/seng/projects/plum-flower/sign-up-api/src): git branch --no-color --no-abbrev -v
Reading /Users/seng/.composer/composer.json
Loading config file /Users/seng/.composer/config.json
Loading config file /Users/seng/.composer/auth.json
Loading config file /Users/seng/.composer/composer.json
Loading config file /Users/seng/.composer/auth.json
Reading /Users/seng/.composer/auth.json
Reading /Users/seng/projects/plum-flower/sign-up-api/src/vendor/composer/installed.json
Reading /Users/seng/.composer/vendor/composer/installed.json
Loading plugin yii\composer\Plugin
Loading plugin Fxp\Composer\AssetPlugin\FxpAssetPlugin
Running 1.2.2 (2016-11-03 17:43:15) with PHP 7.1.0 on Darwin / 16.3.0
> __exec_command: codecept 'run' 'api'
Executing command (CWD): codecept 'run' 'api'
Codeception PHP Testing Framework v2.2.6
Powered by PHPUnit 5.7-dev by Sebastian Bergmann and contributors.

Api Tests (1) ----------------------------------------------------------------
E InfoCept: Get the public information for the main page via api (0.00s)
------------------------------------------------------------------------------


Time: 170 ms, Memory: 10.00MB

There was 1 error:

---------
1) InfoCept: Get the public information for the main page via api
 Test  tests/api/InfoCept.php

  [ExternalUrlException] Codeception\Module\Yii2 can't open external URL: http://plum-flower-sign-up-api.local/v1/info/v1/info


Scenario Steps:

 2. $I->sendGET("/v1/info") at tests/api/InfoCept.php:7
 1. $I->haveHttpHeader("Content-Type","application/json") at tests/api/InfoCept.php:6

#1  Codeception\Module\REST->sendGET
#2  /Users/seng/projects/plum-flower/sign-up-api/src/tests/_support/_generated/ApiTesterActions.php:305
#3  /Users/seng/projects/plum-flower/sign-up-api/src/tests/api/InfoCept.php:7

ERRORS!
Tests: 1, Assertions: 0, Errors: 1.
Script codecept handling the __exec_command event returned with error code 1

Provide test source code if related

<?php

$I = new ApiTester($scenario);

$I->wantTo('Get the public information for the main page via API');
$I->haveHttpHeader('Content-Type', 'application/json');
$I->sendGET('/v1/info');
$I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); // 200
$I->seeResponseIsJson();
$I->seeResponseContainsJson([
    'success' => true,
    'data' => [
      'info' => 'Some information about the <b>company</b>.'
  ]
]);

Details

  • Codeception version: v2.2.6
  • PHP Version: 7.1.0 (also tried with PHP 5.6.x)
  • Operating System: Mac OS X
  • Installation type: Composer
  • List of installed packages (composer show)
    composer-packages.txt

  • Suite configuration:

# tests/api.suite.yml

class_name: ApiTester
modules:
    enabled:
        - REST:
            url: http://plum-flower-sign-up-api.local/v1/info
            depends: Yii2
        - Yii2:

# codeception.yml
include:
  - tests/codeception/common
  - tests/codeception/console
  - tests/codeception/backend
  - tests/codeception/frontend

paths:
  log: tests/codeception/_output

settings:
  colors: true

db:
  dsn:
  username:
  password:

Yii

Most helpful comment

Thank you very much for helping me out. I just ran my first functional test successfully after struggling with it for days!

I did not pay attention to config/test.php because I thought it is config/web.php who handles the app configuration. I copied my request, response & urlManager components from config/web.php to config/test.php and it succeeded.

All 15 comments

You have wrong base API URL set up in the config thus Codeception is requesting http://plum-flower-sign-up-api.local/v1/info/v1/info. Adjust it:

 enabled:
        - REST:
            url: http://plum-flower-sign-up-api.local

I'm sorry, it is a typo in the post. In the real code, it is, in fact, http://plum-flower-sign-up-api.local still throws the same exception

Why is the URL http://plum-flower-sign-up-api.local/v1/info/v1/info then?

I tried few other variations, when I posting the issue, I posted a wrong one. Give me a minute, let me post the exception with the aforementioned url.

image

Which type of test it is? Functional or acceptance?

I'm trying to do functional API tests only.

My main source of confusion is whether we need phpBrowser / Selenium to get REST api working. The documentation claims we don't need browser for functional testing, but REST functional testing does seem to require browser. The app is running via Vagrant, but I run these tests from host machine. Does vagrant setup have to do anything with this?

Functional API test sample code in doc includes phpBrowser
http://codeception.com/docs/10-WebServices

This is the only code snippet I have ever seen for Yii2 API functional test

https://github.com/githubjeka/yii2-rest/blob/master/tests/codeception/rest/functional.suite.yml

They seem to use port 8080. Why didn't they use port 80? Are they using Apache for running main application and use PHP's built-in browser for running tests?

@senguttuvang Don't use domain names in functional testing with Yii2 module unless you use domain based routes (if you had a matching domain route it would work).

Remove url option completely or change it to url: /v1/info

I don't know where you wanted me to make this change, but I have already tried every possible combination of URLs in both API.suite.XML file & tests/API/InfoCept.php

  1. Removed url param from tests/api.suite.yml and kept $I->sendGET('/v1/info'); in tests/api/InfoCept.php
  2. kept /v1/info in tests/api.suite.yml and tried $I->sendGET('/v1/info'); and $I->sendGET('');

In all the cases, it throws 404 exceptions. It doesn't tell which URL it tried to encounter 404. I tried getting into the source code of Codeception, then went through Guzzle, but I got lost at one point.

How the codeception interprets the URL for functional tests? Will it hit the URL to get the result? When you hit the URL from the browser, the web server will populate these data for PHP scripts. How would it determine which URL to hit when running tests from the terminal if we skip url param?

image

Yii2 module doesn't fetch the url - it processes requests without making HTTP request.

The external URL exception was introduced to prevent framework modules from serving request when a link to another website was clicked.

Framework modules process requests to localhost and to other domains that are configured in domain based routes.

You are on a right path and you have to make the path part of your URLs match Yii2 routes.
Please share your route configuration if you can't figure it out.

Thank you very much for helping me out. I just ran my first functional test successfully after struggling with it for days!

I did not pay attention to config/test.php because I thought it is config/web.php who handles the app configuration. I copied my request, response & urlManager components from config/web.php to config/test.php and it succeeded.

Hello everyone,
I have been struggling with the same problem for a couple of days now. I have tried almost everything @senguttuvang & @samdark mentioned and much more. The only difference is that I am using a yii2-app-advanced template via Vagrant.
I have create a new app (api) with a new api codeception suite.

# api.suite.yml
actor: ApiTester
modules:
    enabled:
        - REST:
            url: /api/v1
            depends: Yii2
            part: Json
        - \api\tests\Helper\Api
    config:
        - Yii2

Here is a simple test

<?php
namespace api\tests;
use api\tests\ApiTester;

class ActivityCest
{
    public function checkActivitiesUnauthorized(ApiTester $I)
    {
        $I->sendGET('/activities');
        $I->seeResponseCodeIs(401); // Unauthorized
    }
}

The API is working fine. Testing from my host machine http://localhost:4006/api/v1/activities I am getting the correct response, but when testing whatever I do the response is always 404.

screenshot from 2017-08-28 11-47-34

Any ideas please?

@senguttuvang how did you configured your 'api/config/test.php' file?
Here are my configs:

<?php
// api/config/test-local.php
return yii\helpers\ArrayHelper::merge(
    require(__DIR__ . '/../../common/config/test-local.php'),
    require(__DIR__ . '/main.php'),
    require(__DIR__ . '/main-local.php'),
    require(__DIR__ . '/test.php'),
    [
    ]
);

```php
// api/config/test.php
return [
];

```php
<?php
// api/config/main.php
$params = array_merge(
        require(__DIR__ . '/../../common/config/params.php'), require(__DIR__ . '/../../common/config/params-local.php'), require(__DIR__ . '/params.php')
);

return [
    'id' => 'app-api',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'controllerNamespace' => 'api\controllers',
    'modules' => [
        'v1' => [
            'basePath' => '@app/modules/v1',
            'class' => 'api\modules\v1\Module'
        ],
    ],
    'components' => [
        'user' => [
            'identityClass' => 'common\models\User',
            'enableAutoLogin' => false,
            'enableSession' => false,
        ],
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error', 'warning'],
                ],
            ],
        ],
        'urlManager' => [
            'enablePrettyUrl' => true,
            'enableStrictParsing' => true,
            'showScriptName' => false,
            'rules' => [
                [
                    'class' => 'yii\rest\UrlRule',
                    'controller' => ['v1/activity'],
                    'extraPatterns' => [
                        'OPTIONS update' => 'options',
                        'POST update' => 'update',
                    ]
                ],
            ],
        ],
        'request' => [
            'parsers' => [
                'application/json' => 'yii\web\JsonParser',
            ]
        ],
    ],
    'params' => $params,
];

All suggestions are welcome

@leoshtika and anyone else coming here looking for a valid configuration for the REST API testing, this is what I ended up with

class_name: Api2Tester
modules:
    enabled:
        - Filesystem
        - Asserts
        - Yii2
        - REST:
            url: /v2
            depends: Yii2
            part: Json

Note that my REST url is "/v2" and not "/api/v2". I'm not fully sure of why it's like that but I think it's caused by the 'controller' part of the following section in my configuration:

'urlManager' => [
            'enablePrettyUrl' => true,
            'enableStrictParsing' => true,
            'showScriptName' => false,     // note: this is overwritten in main-local for localhost
            'rules' => [

                //Book
                ['class' => 'yii\rest\UrlRule', 
                    'controller' => ['v2/book'],
                    'extraPatterns' => [
                        'GET index' => 'index',
                        'GET by-favorite-authors' => 'by-favorite-authors',
                        'GET currently-popular' => 'currently-popular',
                        'GET in-favorite-categories' => 'in-favorite-categories',
                    ],
                ],

In my case the problem was that config/test.php didn't have module api defined so I was getting 404. Dunno how I couldn't figure out such a straight forward thing

Was this page helpful?
0 / 5 - 0 ratings