Skip to content

Commit

Permalink
tests: adding unit testing addModule and AddEarlyModule
Browse files Browse the repository at this point in the history
  • Loading branch information
luislard committed May 6, 2024
1 parent f3edf29 commit 6292b7f
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,6 @@ private function addModularityModule(

return $this;
}

$this->initializeModularity($early);
$this->ensureWillBoot();

Expand Down Expand Up @@ -637,6 +636,7 @@ private function handleModularityBoot(
: Modularity\Package::MODULE_EXECUTED;
$this->syncModularityStatus($package, $status);

// TODO: this if condition is running twice when called from sharePackage or sharePackageToBoot
if (
$package->statusIs(Modularity\Package::STATUS_BOOTED)
|| ($onPackageReady && $package->statusIs(Modularity\Package::STATUS_INITIALIZED))
Expand Down
214 changes: 191 additions & 23 deletions tests/unit/AppTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
use Inpsyde\Modularity\Module\ServiceModule;
use Inpsyde\Modularity\Package;
use Inpsyde\WpContext;
use Psr\Container\ContainerInterface;
use Inpsyde\App\Config\Config;
use Brain\Monkey;

class AppTest extends TestCase
Expand All @@ -24,9 +22,14 @@ class AppTest extends TestCase
private $appStatusProp;
/** @var \ReflectionProperty */
private $appBootQueueProp;
/** @var \ReflectionMethod */
private $appHandleModularityBoot;
/** @var \ReflectionMethod */
private $appSyncModularityStatus;

protected function setUp(): void
{
Monkey\Functions\when('remove_all_actions')->justReturn();
$reflectedApp = new \ReflectionClass(App::class);
$this->containerProp = $reflectedApp->getProperty('container');
$this->containerProp->setAccessible(true);
Expand All @@ -37,10 +40,12 @@ protected function setUp(): void
$this->mapProp->setAccessible(true);
$this->appBootQueueProp = $reflectedApp->getProperty('bootQueue');
$this->appBootQueueProp->setAccessible(true);
$this->appHandleModularityBoot = $reflectedApp->getMethod('handleModularityBoot');
$this->appSyncModularityStatus = $reflectedApp->getMethod('syncModularityStatus');
parent::setUp();
}

private function prepareShareToPackageCommon(): array
private function prepareSharePackageCommon(): array
{
\Brain\Monkey\Functions\stubs([
'plugins_url' => static function (): string {
Expand All @@ -59,13 +64,14 @@ private function prepareShareToPackageCommon(): array

$appModule = $this->mockModule($appModuleId, ServiceModule::class);
$appModule->expects('services')->andReturn($this->stubServices($containerServiceId));
$app->addModule($appModule);
$app->addEarlyModule($appModule);

$moduleId = 'my-service-module';
$packageServiceId = 'service-id';

$module = $this->mockModule($moduleId, ServiceModule::class);
$module->expects('services')->andReturn($this->stubServices($packageServiceId));
$expectedReturnFromService = $this->stubServices($packageServiceId);
$module->expects('services')->andReturn($expectedReturnFromService);

$package = Package::new($this->mockProperties())->addModule($module);

Expand All @@ -76,6 +82,7 @@ private function prepareShareToPackageCommon(): array
'moduleId' => $moduleId,
'packageServiceId' => $packageServiceId,
'package' => $package,
'expectedClassFromPackageService' => \ArrayObject::class,
];
}

Expand All @@ -91,44 +98,95 @@ public function testNewWithNoContainer()
static::assertTrue($this->appStatusProp->getValue($app)->isIdle());
}

public function testSharePackageToBootShouldAddPackageServicesToContainerIfPackageIsBooted()
public function testAddEarlyModule()
{
$context = WpContext::new()->force(WpContext::CORE);
$app = App::new(null, null, $context);
$moduleId = 'my-early-service-module';
$moduleServiceId = 'early-service-id';
$module = $this->mockModule($moduleId, ServiceModule::class);
$module->expects('services')->andReturn($this->stubServices($moduleServiceId));
$app->addEarlyModule($module);
// We expect the service is not resolvable if the App Container is not booted
static::assertEquals(null, $app->resolve($moduleServiceId));
$app->boot();
static::assertInstanceOf(\ArrayObject::class, $app->resolve($moduleServiceId));
}

public function testAddModule()
{
$context = WpContext::new()->force(WpContext::CORE);
$app = App::new(null, null, $context);
$moduleId = 'my-early-service-module';
$moduleServiceId = 'early-service-id';
$module = $this->mockModule($moduleId, ServiceModule::class);
$module->expects('services')->andReturn($this->stubServices($moduleServiceId));
$app->addModule($module);
// We expect the service is not resolvable if the App Container is not booted
static::assertEquals(null, $app->resolve($moduleServiceId));
$app->boot();
// TODO: check how addModule was meant to work
static::assertInstanceOf(\ArrayObject::class, $app->resolve($moduleServiceId));

Check failure on line 129 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / tests-unit-php (8.2) / tests-unit-php

Failed asserting that null is an instance of class "ArrayObject".

Check failure on line 129 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / tests-unit-php (7.4) / tests-unit-php

Failed asserting that null is an instance of class "ArrayObject".

Check failure on line 129 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / tests-unit-php (8.0) / tests-unit-php

Failed asserting that null is an instance of class "ArrayObject".

Check failure on line 129 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / tests-unit-php (8.0) / tests-unit-php

Failed asserting that null is an instance of class "ArrayObject".

Check failure on line 129 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / tests-unit-php (8.2) / tests-unit-php

Failed asserting that null is an instance of class "ArrayObject".

Check failure on line 129 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / tests-unit-php (7.4) / tests-unit-php

Failed asserting that null is an instance of class "ArrayObject".

Check failure on line 129 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / tests-unit-php (8.1) / tests-unit-php

Failed asserting that null is an instance of class "ArrayObject".

Check failure on line 129 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / tests-unit-php (7.3) / tests-unit-php

Failed asserting that null is an instance of class "ArrayObject".
}

/**
* Scenario
* Package is booted
* Expectations
* Package services are added to the App Container
* Package does NOT receive any definitions from the WP App Container
*
* @group sharePackageToBoot
* @return void
*/
public function testSharePackageToBootWhenPackageIsBooted()
{
[
'app' => $app,
'containerServiceId' => $containerServiceId,
'packageServiceId' => $packageServiceId,
'package' => $package
] = $this->prepareShareToPackageCommon();
'package' => $package,
'expectedClassFromPackageService' => $expectedClassFromPackageService,
] = $this->prepareSharePackageCommon();

// When package is booted
static::assertTrue($package->boot());

// When we call sharePackageToBoot and pass a booted package
static::assertInstanceOf(App::class, $app->sharePackageToBoot($package));

$container = $this->containerProp->getValue($app);

// The Services from the Package are shared to the App Container
static::assertTrue($container->has($packageServiceId));
static::assertInstanceOf($expectedClassFromPackageService, $app->resolve($packageServiceId));

// But, the services from the App Container are NOT added to the Package since the container is ReadOnly
static::assertInstanceOf(ReadOnlyContainer::class, $package->container());
// But, the services from the App Container are NOT added to the Package since the Package Container is ReadOnly
static::assertFalse($package->container()->has($containerServiceId));
}

public function testSharePackageToBootShouldAddPackageServicesToContainerAfterBootIfPackageIsNotBooted()
/**
* Scenario
* Package is not booted
* The Services added to the App Container are added via addEarlyModule
* App boot is called after
* Expectations
* After App Booting
* App Container can resolve Package services
* Package can resolve App Container Services
* @group sharePackageToBoot
* @return void
*/
public function testSharePackageToBootWhenPackageIsNotBooted(): void
{

[
'app' => $app,
'containerServiceId' => $containerServiceId,
'packageServiceId' => $packageServiceId,
'package' => $package
] = $this->prepareShareToPackageCommon();
'package' => $package,
] = $this->prepareSharePackageCommon();

Monkey\Functions\when('remove_all_actions')->justReturn();

Check warning on line 187 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / coding-standards-analysis-php / coding-standards-php

Multiple adjacent blank lines are not allowed
// When we call sharePackageToBoot passing a NOT booted package
// Notice that the WP App container is not booted at this point neither
static::assertInstanceOf(App::class, $app->sharePackageToBoot($package));

// we don't expect the services from the Package to be in the App Container before booting the App Container
Expand All @@ -154,19 +212,129 @@ public function testSharePackageToBootShouldAddPackageServicesToContainerAfterBo
$currentQueue = $this->appBootQueueProp->getValue($app);
static::assertTrue($currentQueue->contains($package));

// It seems the App Container does not have the service in the container if it is not booted
$container = $this->containerProp->getValue($app);
static::assertFalse($container->has($containerServiceId));

// if we boot the App container
$app->boot();
$container = $this->containerProp->getValue($app);

// We expect the App Container to have the Package services
static::assertTrue($container->has($packageServiceId));
static::assertInstanceOf(\ArrayObject::class, $app->resolve($packageServiceId));

// We expect the Package to be booted
static::assertTrue($package->statusIs(Package::STATUS_BOOTED));

// we expect the App Container services to be in the Package
// sharePackageToBoot is meant to boot the Package
// TODO: FIX THIS
// static::assertTrue($package->container()->has($containerServiceId));
// Note: we can retrieve the service from the App Container because we used App::addEarlyModule
static::assertTrue($package->container()->has($containerServiceId));
static::assertInstanceOf(\ArrayObject::class, $app->resolve($containerServiceId));
}


Check warning on line 233 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / coding-standards-analysis-php / coding-standards-php

Multiple adjacent blank lines are not allowed
public function testSharePackageWhenPackageIsBooted()
{
/**
* @var App $app
*/
[
'app' => $app,
'containerServiceId' => $containerServiceId,
'packageServiceId' => $packageServiceId,
'package' => $package,
'expectedClassFromPackageService' => $expectedClassFromPackageService,
] = $this->prepareSharePackageCommon();

// When package is booted
static::assertTrue($package->boot());

// When we call sharePackage and pass a booted package
static::assertInstanceOf(App::class, $app->sharePackage($package));

// The Services from the Package are shared to the App Container
static::assertInstanceOf($expectedClassFromPackageService, $app->resolve($packageServiceId));

// But, the services from the App Container are NOT added to the Package since the Package Container is ReadOnly
static::assertFalse($package->container()->has($containerServiceId));
}


Check warning on line 260 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / coding-standards-analysis-php / coding-standards-php

Multiple adjacent blank lines are not allowed
/**
* Scenario
* Package is not booted
* The Services added to the App Container are added via addEarlyModule
* App boot is called after
* Expectations
* After App Booting
* App Container can resolve Package services
* Package can resolve App Container Services
* @group sharePackageToBoot
* @return void
*/
public function testSharePackageWhenPackageIsNotBooted(): void
{

[
'app' => $app,
'containerServiceId' => $containerServiceId,
'packageServiceId' => $packageServiceId,
'package' => $package,
] = $this->prepareSharePackageCommon();


Check warning on line 283 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / coding-standards-analysis-php / coding-standards-php

Multiple adjacent blank lines are not allowed

Check warning on line 284 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / coding-standards-analysis-php / coding-standards-php

Multiple adjacent blank lines are not allowed
// When we call sharePackageToBoot passing a NOT booted package
// Notice that the WP App container is not booted at this point neither
static::assertInstanceOf(App::class, $app->sharePackage($package));

// we don't expect the services from the Package to be in the App Container before booting the App Container
$container = $this->containerProp->getValue($app);
static::assertFalse($container->has($packageServiceId));

// we don't expect the package to have container to be accessible because is not booted nor built.
static::assertFalse($package->statusIs(Package::STATUS_BOOTED));
try {
$package->container();
} catch (\Exception $exception) {
static::assertStringContainsString(
'Can\'t obtain the container',
$exception->getMessage()
);
}

// It is only connected with a new Package that is booted already
static::assertEquals([ "inpsyde-wp-app" => true ], $package->connectedPackages());

// we manually boot the package in here since sharePackage enqueues a callback waiting for this
$package->boot();

// we have to mimic the internals of the waitForPackageBoot
// (we are hardcoding a callback there)
$this->appSyncModularityStatus->invoke(
$app,
$package,
Package::MODULE_ADDED
);

$this->appHandleModularityBoot->invoke(
$app,
$package,
true,

Check failure on line 321 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / coding-standards-analysis-php / coding-standards-php

Trailing comma's are not allowed in function calls in PHP 7.2 or earlier
);

// package can't see the service from app container if the Wp App Container is not booted
static::assertFalse($package->container()->has($containerServiceId));

// if we boot the App container
$app->boot();

// We expect the Package to have container services
static::assertTrue($package->container()->has($containerServiceId));

// We expect the App Container to have the Package services
static::assertInstanceOf(\ArrayObject::class, $app->resolve($packageServiceId));

// Note: we can retrieve the service from the App Container because we used App::addEarlyModule
static::assertInstanceOf(\ArrayObject::class, $app->resolve($containerServiceId));
}

}

Check failure on line 340 in tests/unit/AppTest.php

View workflow job for this annotation

GitHub Actions / coding-standards-analysis-php / coding-standards-php

The closing brace for the class must go on the next line after the body

0 comments on commit 6292b7f

Please sign in to comment.