Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
19 changes: 14 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
- Enumerated Constants: `PascalCase` (eg. `DeepSkyBlue`)
- Class properties: `_camelCase` (eg. `_propertyOfClass`, `_styleFieldNames`)
- Namespace: `Prado\{Module}` (eg. `Prado\Web\UI\TControl`)
- Unit test namespace: `Prado\Test\Unit\{Directory}` mirroring `tests/unit/` (eg. `Prado\Test\Unit\Web\UI\TControlTest`)
- Web Page template file extensions: `.page` with `.php` backing
- MasterClass and Template file extension: `.tpl` with `.php` backing
- Prado TControl template tag prefix: `<com:` (eg. `<com:TMain />`)
Expand Down Expand Up @@ -85,6 +86,7 @@ Docblocks inform and describe; it is not persuasive writing.

### Imports and Includes
- Use PSR-4 autoloading - no manual includes required
- Unit test classes autoload through the Composer `autoload-dev` PSR-4 mapping (`Prado\Test\Unit\` → `tests/unit/`); tests do not `require` class files
- All framework classes are accessed via namespace prefixes
- Third-party libraries are loaded via Composer
- Use proper `use` statements for namespaces at the top of PHP files
Expand Down Expand Up @@ -188,14 +190,20 @@ All instances self-register in `Prado.Registry[controlId]` on construction and a
- Unit test functions must comprehensively assert both typical and edge cases
- Maximal code coverage is required
- Test error conditions and exception handling
- Use `tests/unit/PradoUnit` infrastructure for (bootstrapped in phpunit):
- Unit test classes use the `Prado\Test\Unit\` namespace, autoloaded by Composer (`autoload-dev` PSR-4 → `tests/unit/`).
- The namespace follows the directory: `tests/unit/Web/UI/TControlTest.php` → `Prado\Test\Unit\Web\UI\TControlTest`.
- A class used by another file lives in its own file named after the class. Fixtures used only by one test file stay in that file.
- Directories holding classes use PascalCase, except where they mirror a lowercase framework namespace (`I18N/core`).
- Class names in strings, templates (`<com:…>`), and XML configuration are fully qualified; use `Foo::class` in PHP.
- Global-namespace fixtures (`Security/app/prado3stubs/`, `Exceptions/TErrorHandlerTestGlobalClass.php`) and `PHPStan/Fixtures/` are excluded from the classmap and are not autoloaded.
- Test classes are inside `Prado\*`: a default log category is the test class, and an ActiveRecord fixture needs `const TABLE`.
- Helper classes in their own file must not end in `Test`; phpunit collects `*Test.php` files as tests.
- Use `Prado\Test\Unit\PradoUnit` infrastructure for:
- access to an object's protected/private properties
- invoking protected/private methods
- restore global variables to their initial state
- save and restore all of an object's properties
- automatically is included in the bootstrap
- includes everything in `tests/unit/Harness/` automatically (bootstrap)
- `Harness` is where test classes of Prado framework classes are located for general use
- `Harness/` (`Prado\Test\Unit\Harness\`) holds test classes designed for reuse across the Prado tests
- Traits for unit test classes are in `Harness/Traits/`
- Use mock objects only where appropriate, and check PradoUnit for a common solution first.
- Functional tests should verify complete user workflows
Expand Down Expand Up @@ -300,7 +308,8 @@ All instances self-register in `Prado.Registry[controlId]` on construction and a
│ ├── js/ # vitest js unit tests
│ ├── playwright/ # Functional tests
│ ├── test_tools/ # phpunit bootstrap and utilities
│ └── unit/ # phpunit tests for './framework/' classes
│ └── unit/ # phpunit tests for './framework/' classes; namespace Prado\Test\Unit (autoload-dev PSR-4)
│ ├── Harness/ # Reusable test classes and traits (Prado\Test\Unit\Harness)
│ └── PradoUnit.php # Unit Test Helper
├── CLAUDE.md # The Memory file for the directory
├── composer.json # Package configuration
Expand Down
17 changes: 12 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ TApplication
| Enumerated Constants | `PascalCase` | `DeepSkyBlue` |
| Class properties| `_camelCase` | `_propertyOfClass`, `_styleFieldNames` |
| Namespaces | `Prado\{Module}` | `Prado\Web\UI\TControl` |
| Unit test namespaces | `Prado\Test\Unit\{Directory}` | `Prado\Test\Unit\Web\UI\TControlTest` |
| Web Page templates | `.page` with `.php` backing | `Home.page`, `Home.php` |
| MasterClass and Template files | `.tpl` with `.php` backing | `MyPortlet.tpl`, `MyPortlet.php` |
| TControl tag prefix | `<com:` | `<com:TMain />` |
Expand All @@ -134,19 +135,25 @@ TApplication
## Test Bootstrap

Tests require a running `TApplication`.
The bootstrap (`tests/test_tools/phpunit_bootstrap.php`) instantiates one from `tests/test_tools/Security/app/`; it may change through the unit tests.
The bootstrap (`tests/test_tools/phpunit_bootstrap.php`) instantiates one from `tests/unit/Security/app/`; it may change through the unit tests.
Database tests need MySQL/PostgreSQL initialized from `tests/initdb_mysql.sql` / `tests/initdb_pgsql.sql`.

## Testing

- Use `tests/unit/PradoUnit` infrastructure for (bootstrapped in phpunit):
- Unit test classes use the `Prado\Test\Unit\` namespace, autoloaded by Composer (`autoload-dev` PSR-4 → `tests/unit/`).
- The namespace follows the directory: `tests/unit/Web/UI/TControlTest.php` → `Prado\Test\Unit\Web\UI\TControlTest`.
- A class used by another file lives in its own file named after the class. Fixtures used only by one test file stay in that file.
- Directories holding classes use PascalCase, except where they mirror a lowercase framework namespace (`I18N/core`).
- Class names in strings, templates (`<com:…>`), and XML configuration are fully qualified; use `Foo::class` in PHP.
- Global-namespace fixtures (`Security/app/prado3stubs/`, `Exceptions/TErrorHandlerTestGlobalClass.php`) and `PHPStan/Fixtures/` are excluded from the classmap and are not autoloaded.
- Test classes are inside `Prado\*`: a default log category is the test class, and an ActiveRecord fixture needs `const TABLE`.
- Helper classes in their own file must not end in `Test`; phpunit collects `*Test.php` files as tests.
- Use `Prado\Test\Unit\PradoUnit` infrastructure for:
- access to an object's protected/private properties
- invoking protected/private methods
- restore global variables to their initial state
- save and restore all of an object's properties
- automatically is included in the bootstrap
- includes everything in `tests/unit/Harness/` automatically (bootstrap)
- `Harness` is where test classes of Prado framework classes are located for general use
- `Harness/` (`Prado\Test\Unit\Harness\`) holds test classes designed for reuse across the Prado tests
- Traits for unit test classes are in `Harness/Traits/`

## Code Style
Expand Down
2 changes: 1 addition & 1 deletion agents/framework/PHPStan/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ PHPUnit tests live in `tests/unit/PHPStan/PHPStanExtensionsTest.php`. Each exten
1. **Without extension** (`phpstan-no-extensions.neon`) — verifies the fixture file DOES produce PHPStan errors.
2. **With extension** (`phpstan.neon.dist`) — verifies the fixture file produces ZERO errors.

Fixture files are in `tests/unit/PHPStan/fixtures/`:
Fixture files are in `tests/unit/PHPStan/Fixtures/`:
- `HasMethodFixture.php` — `TComponent::hasMethod()` guard patterns
- `MethodVisibleFixture.php` — `Prado::method_visible()` guard patterns
- `DynamicMethodsFixture.php` — `dy*` / `fx*` dynamic method calls
Expand Down
12 changes: 10 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@
"laravel/serializable-closure": "^2.0"
},
"require-dev" : {
"ext-bcmath": "*",
"ext-bz2": "*",
"phpunit/phpunit" : "^10",
"php-webdriver/webdriver": "^1",
"phpdocumentor/shim": "^3",
Expand Down Expand Up @@ -96,6 +94,16 @@
"Prado\\": "framework"
}
},
"autoload-dev": {
"psr-4": {
"Prado\\Test\\Unit\\": "tests/unit/"
},
"exclude-from-classmap": [
"tests/unit/PHPStan/Fixtures/",
"tests/unit/Security/app/prado3stubs/",
"tests/unit/Exceptions/TErrorHandlerTestGlobalClass.php"
]
},
"config": {
"platform": {
"php": "8.1"
Expand Down
2 changes: 1 addition & 1 deletion framework/PHPStan/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ PHPUnit tests live in `tests/unit/PHPStan/PHPStanExtensionsTest.php`. Each exten
1. **Without extension** (`phpstan-no-extensions.neon`) — verifies the fixture file DOES produce PHPStan errors.
2. **With extension** (`phpstan.neon.dist`) — verifies the fixture file produces ZERO errors.

Fixture files are in `tests/unit/PHPStan/fixtures/`:
Fixture files are in `tests/unit/PHPStan/Fixtures/`:
- `HasMethodFixture.php` — `TComponent::hasMethod()` guard patterns
- `MethodVisibleFixture.php` — `Prado::method_visible()` guard patterns
- `DynamicMethodsFixture.php` — `dy*` / `fx*` dynamic method calls
Expand Down
2 changes: 1 addition & 1 deletion framework/Web/Javascripts/TJavaScript.php
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ public static function encode($value, $toMap = true, $encodeEmptyStrings = false
} elseif (is_int($value)) {
return "$value";
} elseif (is_float($value)) {
if(is_nan($value)) {
if (is_nan($value)) {
return 'NAN';
}
switch ($value) {
Expand Down
5 changes: 4 additions & 1 deletion tests/test_tools/phpunit_bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
* the right package in unit test and code coverage reports.
*/

// Composer autoloads the framework (Prado\) and the unit-test classes
// (Prado\Test\Unit\ via autoload-dev PSR-4).
require_once(__DIR__ . '/../../vendor/autoload.php');
require_once(__DIR__ . '/../../framework/Prado.php');
require_once(__DIR__ . '/../unit/PradoUnit.php');

use Prado\Test\Unit\PradoUnit;

// Capture the process-global baseline (superglobals, cwd, timezone,
// error_reporting, include_path) BEFORE the bootstrap TApplication runs and
Expand Down
14 changes: 14 additions & 0 deletions tests/unit/AppTestModule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Prado\Test\Unit;

use Prado\TModule;

/**
* A minimal concrete module for use in module-management tests.
* TModule is abstract, so we need a concrete subclass.
*/
class AppTestModule extends TModule
{
public function init($config) {}
}
24 changes: 24 additions & 0 deletions tests/unit/BarBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Prado\Test\Unit;

use Prado\Util\IInstanceCheck;

class BarBehavior extends PreBarBehavior implements IInstanceCheck
{
private $_instanceReturn;

public function moreFunction($laa, $sol)
{
return pow($laa + $sol + 1, 2);
}

public function isinstanceof($class, $instance = null)
{
return $this->_instanceReturn;
}
public function setInstanceReturn($value)
{
$this->_instanceReturn = $value;
}
}
13 changes: 13 additions & 0 deletions tests/unit/BarClassBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Prado\Test\Unit;

use Prado\Util\TClassBehavior;

class BarClassBehavior extends TClassBehavior
{
public function moreFunction($object, $laa, $sol)
{
return true;
}
}
15 changes: 15 additions & 0 deletions tests/unit/BarClassBehaviorWithEvents.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Prado\Test\Unit;


class BarClassBehaviorWithEvents extends BarClassBehavior
{
public function events()
{
return ['onMyEvent' => ['barClassEventHandler', function ($sender, $param) { return time(); }]];
}
public function barClassEventHandler($sender, $param)
{
}
}
40 changes: 40 additions & 0 deletions tests/unit/BehaviorTestBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Prado\Test\Unit;

use Prado\Util\TBehavior;

class BehaviorTestBehavior extends TBehavior
{
private $excitement = 'faa';
public $_config;
public const NULL_CONFIG = "null-config";

public function init($config)
{
if ($config == null) {
$config = self::NULL_CONFIG;
}
$this->_config = $config;
}
public function getExcitement()
{
return $this->excitement;
}
public function setExcitement($value)
{
$this->excitement = $value;
}
public function getReadOnly()
{
return true;
}

public function onBehaviorEvent($sender, $param, $responsetype = null, $postfunction = null)
{
return $this->getOwner()->raiseEvent('onBehaviorEvent', $sender, $param, $responsetype, $postfunction);
}
public function fxGlobalBehaviorEvent($sender, $param)
{
}
}
5 changes: 4 additions & 1 deletion tests/unit/Caching/TAPCCacheTest.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
<?php

namespace Prado\Test\Unit\Caching;

use Prado\Caching\TAPCCache;
use Prado\Exceptions\TConfigurationException;
use Prado\TApplication;
use Prado\Exceptions\TNotSupportedException;

class TAPCCacheTest extends PHPUnit\Framework\TestCase
class TAPCCacheTest extends \PHPUnit\Framework\TestCase
{
protected $app;
protected static $cache = null;
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/Caching/TApplicationStateCacheDependencyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* @license https://github.com/pradosoft/prado/blob/master/LICENSE
*/

require_once __DIR__ . '/../PradoUnitRequires.php';
namespace Prado\Test\Unit\Caching;

use Prado\Caching\TApplicationStateCacheDependency;
use Prado\Prado;
Expand All @@ -25,7 +25,7 @@
* Each test saves the current application mode in setUp() and restores it in
* tearDown() so this suite does not affect other tests.
*/
class TApplicationStateCacheDependencyTest extends PHPUnit\Framework\TestCase
class TApplicationStateCacheDependencyTest extends \PHPUnit\Framework\TestCase
{
private string $_originalMode;

Expand Down
6 changes: 4 additions & 2 deletions tests/unit/Caching/TCacheDependencyListTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
* @license https://github.com/pradosoft/prado/blob/master/LICENSE
*/

namespace Prado\Test\Unit\Caching;

use Prado\Caching\ICacheDependency;
use Prado\Caching\TCacheDependencyList;
use Prado\Exceptions\TInvalidDataTypeException;

/**
* Unit tests for {@see \Prado\Caching\TCacheDependencyList}.
*/
class TCacheDependencyListTest extends PHPUnit\Framework\TestCase
class TCacheDependencyListTest extends \PHPUnit\Framework\TestCase
{
// -------------------------------------------------------------------------
// Helpers
Expand Down Expand Up @@ -62,7 +64,7 @@ public function testInsertPlainObjectThrows(): void
{
$this->expectException(TInvalidDataTypeException::class);
$list = new TCacheDependencyList();
$list->add(new stdClass());
$list->add(new \stdClass());
}

public function testInsertAtValidPositionSucceeds(): void
Expand Down
6 changes: 5 additions & 1 deletion tests/unit/Caching/TCacheFileTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
* @license https://github.com/pradosoft/prado/blob/master/LICENSE
*/

namespace Prado\Test\Unit\Caching;

use Prado\Test\Unit\Harness\Caching\TTestFileCache;

/**
* Unit tests for {@see \Prado\Caching\TCacheFileTrait}, exercised through the
* {@see TTestFileCache} harness (which uses the trait). Covers the filesystem read/write
* seams, including the optional exclusive-lock write parameter.
*/
class TCacheFileTraitTest extends PHPUnit\Framework\TestCase
class TCacheFileTraitTest extends \PHPUnit\Framework\TestCase
{
private string $dir;
private TTestFileCache $cache;
Expand Down
5 changes: 4 additions & 1 deletion tests/unit/Caching/TCacheSizeTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@
* @license https://github.com/pradosoft/prado/blob/master/LICENSE
*/

namespace Prado\Test\Unit\Caching;

use Prado\Caching\ICacheSize;
use Prado\Test\Unit\Harness\Caching\TTestFileCache;

/**
* Unit tests for {@see \Prado\Caching\TCacheSizeTrait}, exercised through the
* {@see TTestFileCache} harness (which uses the trait). Covers size-string parsing,
* the MaximumSize property, over-capacity detection, and the running-size accessors.
*/
class TCacheSizeTraitTest extends PHPUnit\Framework\TestCase
class TCacheSizeTraitTest extends \PHPUnit\Framework\TestCase
{
private string $dir;

Expand Down
5 changes: 4 additions & 1 deletion tests/unit/Caching/TCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,21 @@
* @license https://github.com/pradosoft/prado/blob/master/LICENSE
*/

namespace Prado\Test\Unit\Caching;

use Prado\Caching\ICache;
use Prado\Caching\ICacheDependency;
use Prado\Exceptions\TConfigurationException;
use Prado\TApplication;
use Prado\Test\Unit\Harness\Caching\TTestCache;

/**
* Unit tests for the abstract {@see \Prado\Caching\TCache} base, exercised through the
* {@see TTestCache} harness (an array-backed concrete TCache). Covers the public ICache
* behavior (key prefixing/hashing, dependency wrapping, empty-value delete, ArrayAccess),
* primary-cache registration, and the time()/microtime() clock seams.
*/
class TCacheTest extends PHPUnit\Framework\TestCase
class TCacheTest extends \PHPUnit\Framework\TestCase
{
private TApplication $app;

Expand Down
Loading
Loading