Cake3 Fixtures not being built during unit testing cake plugin - phpunit

I have a cakephp 3.7 plugin as its own stand-alone project. But am encountering the failures below when running unit tests. It seems after moving this outside of a parent project, the fixtures are no longer being built. Not sure how to instruct cake to build them.
Cake\Database\Exception: Cannot describe teams. It has 0 columns.
Here is my tests/bootstrap file. These tests were previously working until I decided to move this plugin out of the parent project.
<?php
$findRoot = function ($root) {
do {
$lastRoot = $root;
$root = dirname($root);
if (is_dir($root . '/vendor/cakephp/cakephp')) {
return $root;
}
} while ($root !== $lastRoot);
throw new Exception("Cannot find the root of the application, unable to run tests");
};
$root = $findRoot(__FILE__);
unset($findRoot);
chdir($root);
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
define('ROOT', $root);
define('APP_DIR', 'App');
define('WEBROOT_DIR', 'webroot');
define('APP', ROOT . '/tests/');
define('CONFIG', ROOT . '/tests/config/');
define('WWW_ROOT', ROOT . DS . WEBROOT_DIR . DS);
define('TESTS', ROOT . DS . 'tests' . DS);
define('TMP', ROOT . DS . 'tmp' . DS);
define('LOGS', TMP . 'logs' . DS);
define('CACHE', TMP . 'cache' . DS);
define('CAKE_CORE_INCLUDE_PATH', ROOT . '/vendor/cakephp/cakephp');
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
define('CAKE', CORE_PATH . 'src' . DS);
require_once ROOT . '/vendor/cakephp/cakephp/src/basics.php';
require ROOT . '/vendor/autoload.php';
use Cake\Core\Configure;
use Cake\Core\Configure\Engine\PhpConfig;
try {
Configure::config('default', new PhpConfig());
Configure::load('app', 'default', false);
} catch (\Exception $e) {
exit($e->getMessage() . "\n");
}
$TMP = new \Cake\Filesystem\Folder(TMP);
$TMP->create(TMP . 'cache/models', 0777);
$TMP->create(TMP . 'cache/persistent', 0777);
$TMP->create(TMP . 'cache/views', 0777);
$cache = [
'default' => [
'engine' => 'File',
],
'_cake_core_' => [
'className' => 'File',
'prefix' => '_cake_core_',
'path' => CACHE . 'persistent/',
'serialize' => true,
'duration' => '+10 seconds',
],
'_cake_model_' => [
'className' => 'File',
'prefix' => '_cake_model_',
'path' => CACHE . 'models/',
'serialize' => 'File',
'duration' => '+10 seconds',
],
'_cake_method_' => [
'className' => 'File',
'prefix' => '_cake_method_',
'path' => CACHE . 'models/',
'serialize' => 'File',
'duration' => '+10 seconds',
],
];
Cake\Cache\Cache::setConfig($cache);
if (file_exists($root . '/config/bootstrap.php')) {
require $root . '/config/bootstrap.php';
}
if (!getenv('db_dsn')) {
putenv('db_dsn=sqlite:///:memory:');
}
Cake\Datasource\ConnectionManager::setConfig('test', [
'url' => getenv('db_dsn'),
'timezone' => 'UTC'
]);
phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
colors="true"
stopOnFailure="false"
bootstrap="./tests/bootstrap.php"
>
<php>
<ini name="memory_limit" value="-1"/>
<ini name="apc.enable_cli" value="1"/>
</php>
<!-- Add any additional test suites you want to run here -->
<testsuites>
<testsuite name="YummySearch Test Suite">
<directory>./tests/TestCase</directory>
</testsuite>
</testsuites>
<!-- configure code coverage -->
<filter>
<whitelist>
<directory suffix=".php">./src/</directory>
</whitelist>
</filter>
<!-- Setup a listener for fixtures -->
<listeners>
<listener
class="Cake\TestSuite\Fixture\FixtureInjector">
<arguments>
<object class="Cake\TestSuite\Fixture\FixtureManager" />
</arguments>
</listener>
</listeners>
</phpunit>

Related

understand callback function in wordpress

I'd like to understand what $args['id'] mean in the add_settings_section() callback function, and how the loop get the id of every section:
here my array to add sections information:
$ap_sections = [
'section-theme-settings' => [
'title' => 'Theme settings',
'desc' => 'General theme settings'
],
'section-styling-settings' => [
'title' => 'Styling settings',
'desc' => 'settings for editing colors, fonts and css.'
],
'section-social-settings' => [
'title' => 'Social settings',
'desc' => 'Edit your social media profiles.'
]
];
here my loop:
foreach ( $ap_sections as $section_id => $section_value ) {
add_settings_section( $section_id, $section_value['title'], 'ap_render_section', 'ap-theme-options' );
}
and here ap_render_section callback function:
function ap_render_section($args) {
global $ap_sections;
echo '<p>' . $ap_sections[ $args['id'] ] ['desc'] . '</p>';
echo '<hr />';
}
my goal is understand not copy and pate code
Each section should have unique ID. And first parameter in add_settings_section function is ID of that added section.
Check the code from WP Codex:
add_settings_section(
'eg_setting_section',
'Example settings section in reading',
'eg_setting_section_callback_function',
'reading'
);
function eg_setting_section_callback_function( $arg ) {
// echo section intro text here
echo '<p>id: ' . $arg['id'] . '</p>'; // id: eg_setting_section
echo '<p>title: ' . $arg['title'] . '</p>'; // title: Example settings section in reading
echo '<p>callback: ' . $arg['callback'] . '</p>'; // callback: eg_setting_section_callback_function
}
As you can see, $arg['id'] here is "eg_setting_section".
So, add_settings_section function passes your added unique slug and title to callback function as array elements.

How can I populate/imitate server variables in PHPUnit Test cases using Symfony3?

How can I populate/imitate server variables in PHPUnit Test cases using Symfony3?
I try to create functional tests for my symfony3 application.
I use LiipFunctionalTestBundle.
I have a special $_SERVER variable which contains the country of the visitor. The behavior of the action strongly depends on it.
I try to populate it in my test case.
Here is the content of the phpunit.xml.dist file which is based on Setting PHP INI settings, Constants and Global Variables in PHPUnit
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="app/autoload.php"
>
<php>
<ini name="error_reporting" value="-1" />
<server name="KERNEL_DIR" value="app/" />
<server name="COUNTRY_CODE" value="AT" />
<server name="HTTP_COUNTRY_CODE" value="AT" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>src</directory>
<exclude>
<directory>src/*Bundle/Resources</directory>
<directory>src/*/*Bundle/Resources</directory>
<directory>src/*/Bundle/*Bundle/Resources</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
$client = static::createClient(array(), array(
'PHP_AUTH_USER' => "test_login",
'PHP_AUTH_PW' => "test_password",
'HTTP_HOST' => "phpunit.symfony.dev",
'REQUEST_URI' => "/app/setting",
'DOCUMENT_ROOT' => "/path/to/docroot/app/web"
));
and
$this->client->request(
'GET',
'/app/profile',
array(),
array(),
array(
'COUNTRY_CODE' => "AT",
'HTTP_COUNTRY_CODE' => "AT",
'SCRIPT_NAME' => "thing/thong",
'HTTP_REFERER' => '/foo/bar'
)
);
when I get the request in the unittest by dump($this->client->getRequest()); then I see my variables:
Symfony\Component\HttpFoundation\Request {#1009
+attributes: Symfony\Component\HttpFoundation\ParameterBag {#1008
#parameters: []
}
+request: Symfony\Component\HttpFoundation\ParameterBag {#1093
#parameters: []
}
+query: Symfony\Component\HttpFoundation\ParameterBag {#1092
#parameters: []
}
+server: Symfony\Component\HttpFoundation\ServerBag {#993
#parameters: array:22 [
"PHP_AUTH_USER" => "test_login"
"PHP_AUTH_PW" => "test_password"
"SERVER_NAME" => "phpunit.symfony.dev"
"HTTP_HOST" => "phpunit.symfony.dev"
"REQUEST_URI" => "/app/setting"
"DOCUMENT_ROOT" => "/path/to/docroot/app/web"
"COUNTRY_CODE" => "AT"
"HTTP_COUNTRY_CODE" => "AT"
"SCRIPT_NAME" => "thing/thong"
"HTTP_REFERER" => "/foo/bar"
"SERVER_PORT" => 80
"HTTP_USER_AGENT" => "Symfony BrowserKit"
"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
"HTTP_ACCEPT_LANGUAGE" => "en-us,en;q=0.5"
"HTTP_ACCEPT_CHARSET" => "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
"REMOTE_ADDR" => "127.0.0.1"
"SCRIPT_FILENAME" => ""
"SERVER_PROTOCOL" => "HTTP/1.1"
"REQUEST_TIME" => 1485369277
"PATH_INFO" => ""
"REQUEST_METHOD" => "GET"
"QUERY_STRING" => ""
]
}
but for some reason, in the action
public function indexAction(Request $request)
{
dump($_SERVER);
}
the $_SERVER variable contains the Shell and Environmental Variables instead:
"LESSOPEN" => "| /usr/bin/lesspipe %s"
"PROFILEHOME" => ""
"GNOME_KEYRING_PID" => ""
"USER" => "developer"
"LANGUAGE" => "en_US"
"UPSTART_INSTANCE" => ""
"XDG_SEAT" => "seat0"
"SESSION" => "sess$58479"
"XDG_SESSION_TYPE" => "x11"
"SHLVL" => "2"
"HOME" => "/home/developer"
"DESKTOP_SESSION" => "sess$58479"
"QT_LINUX_ACCESSIBILITY_ALWAYS_ON" => "1"
"SHELL_SESSION_ID" => "78c26972fe6040009409a2bd8748034d"
"GTK_MODULES" => "gail:atk-bridge:unity-gtk-module"
"XDG_SEAT_PATH" => "/org/freedesktop/DisplayManager/Seat0"
"KONSOLE_DBUS_SESSION" => "/Sessions/1"
What do I do wrong?
Is there any way to imitate the server variables in command line, using Symfony3 and phpunit?
I was on a wrong way. I can access the server variables through the $request object:
public function indexAction(Request $request)
{
dump($request->server->get('HTTP_HOST'));
dump($request->server->get('COUNTRY_CODE'));
}

Yii2 module (not under /vendor folder) class not found in config/main.php

I've created a module under folder api (which itself is same level as backend & frontend in yii2 advanced app).
Folder structure:
api
-- common
------ controllers
------ models
-- config
-- modules
------ v1
---------- controllers
---------- models
-- runtime
-- tests
-- web
In api/config/main.php:
return [
'id' => 'app-api',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'modules' => [
'v1' => [
'basePath' => '#app/modules/v1',
'class' => 'api\modules\v1\Module'
]
],
I get error:
ReflectionException
Class api\modules\v1\Module does not exist
The class is definitely there.
I've run a composer dumpautoload (no errors).
urlManager in config/main.php:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
'v1/site/index' => 'v1/site/index', //module/controller/action
],
]
Any help much appreciated,
thanks
OK got it:
in common/config/bootstrap.php, add:
Yii::setAlias('#api', dirname(dirname(__DIR__)) . '/api');
Then in config/main.php use:
'modules' => [
'v1' => [
'basePath' => '#api/modules/v1',
'class' => 'api\modules\v1\Module'
]
],
This seems to work, thanks guys
Thanks, gvanto. Also check whether you include common/config/bootstrap.php in \api\web\index.php . Like here
<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/../../vendor/autoload.php');
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
require (__DIR__ . '/../../common/config/bootstrap.php');
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../../common/config/main.php'),
require(__DIR__ . '/../../common/config/main-local.php'),
require(__DIR__ . '/../config/main.php'),
require(__DIR__ . '/../config/main-local.php')
);
$application = new yii\web\Application($config);
$application->run();
that was my mistake. Maybe it will help someone

Yii2 console script not working

I want to automatically download my database backup weekly. I'm using xampp on windows. I've google around and found that I've to make use of windows task scheduler and the action script in my console controller. I've read this and this and tried running the command from command prompt. I'm getting 'Unknown command'.
My code in console controller for now just for testing
<?php
namespace console\controllers;
use Yii;
use yii\console\Controller;
/**
* Cron controller
*/
class TestController extends Controller {
public function actionIndex() {
echo "cron service runnning";
}
}
And my main config file
<?php
$params = array_merge(
require(__DIR__ . '/../../common/config/params.php'),
require(__DIR__ . '/../../common/config/params-local.php'),
require(__DIR__ . '/params.php'),
require(__DIR__ . '/params-local.php')
);
return [
'id' => 'app-console',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'controllerNamespace' => 'console\controllers',
'components' => [
'log' => [
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'authManager' => [
'class' => 'yii\rbac\DbManager',
],
],
'modules' => [
'rbac' => [
'class' => 'johnitvn\rbacplus\Module'
]
],
'params' => $params,
];
The error I'm getting
Make sure you have TestController.php file in console/controllers folder and its name is written correctly.
Then from project root folder you can call your command like that:
php yii test/index
or just:
php yii test
(because index is a default action (configured in $defaultAction) and you can omit it).
If you are outside of project folder, make sure to provide correct path:
php /path/to/project/folder/yii test

Silex phpunit not matching routes

I am trying to write some tests for my Silex app and have run into an issue.
I have the following phpunit.xml file
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="./bootstrap.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
>
<testsuites>
<testsuite name="Management Test Suite">
<directory>./</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>../src/</directory>
</whitelist>
</filter>
</phpunit>
The bootstrap code is
<?php
use Symfony\Component\HttpKernel\Client;
function getJSONResponse($app, Client $client, $url, $params = array())
{
$params['test_key'] = $app['test_key'];
$client->request('GET', $url, $params);
$response = $client->getResponse();
$data = json_decode($response->getContent(), true);
return $data;
}
My first test file is as follows
<?php
require_once $_SERVER['frog_docroot'] . '/www/vendor/autoload.php';
class DefaultTest extends Silex\WebTestCase
{
public function createApplication()
{
return require $_SERVER['frog_docroot'] . '/www/src/app.php';
}
public function testInvalidUrlThrowsException()
{
$client = $this->createClient();
$data = getJSONResponse($this->app, $client, '/some/url/that/does/not/exist');
$this->assertContains('No route found for "GET /some/url/that/does/not/exist"', $data['message']);
}
}
And my second one is
<?php
require_once $_SERVER['frog_docroot'] . '/www/vendor/autoload.php';
class AnotherTest extends Silex\WebTestCase
{
public function createApplication()
{
return require $_SERVER['frog_docroot'] . '/www/src/app.php';
}
public function testSearchReturnsResults()
{
$client = $this->createClient();
$data = getJSONResponse($this->app, $client, '/packages/search', array(
'search' => 'something',
'offset' => 0,
'limit' => 10,
));
$this->assertSame(array(
'data' => array(
'1' => 'Some Package',
),
'offset' => 0,
'limit' => 10,
), $data);
}
}
The issue is that if I run the test individually they both pass.
If I run them as part of the test suite an exception is thrown
There was 1 failure:
1) AnotherTest::testSearchReturnsResults
Failed asserting that Array (
'message' => 'No route found for "GET /packages/search"'
'code' => 0
) is identical to Array (
'data' => Array (
'1' => 'Some Package'
)
'offset' => 0
'limit' => 10
'more' => false
).
Is there anything obviously wrong with how I am trying to write the tests?
Cheers
I ran into the same issue. All I had to do (although I didn't like that solution) was to use require and include instead of require_once and include_once

Resources