mirror of
https://github.com/Vateron-Media/XC_VM.git
synced 2026-11-05 19:03:33 +01:00
ModuleStore reads the catalogue from the core extension (XC_VM::extensions_list) and asks XC_VM::plugins_check whether the Modules API key bought each paid module. Every module is listed, marked free, purchased or paid, with what is installed of it here, matched by the manifest's update.slug. Cached 5 minutes per API key; a store that did not answer is not cached.
94 lines
3.8 KiB
PHP
94 lines
3.8 KiB
PHP
<?php
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use XcVm\Core\Module\ModuleStore;
|
|
|
|
/**
|
|
* The official store as the modules page lists it (Core\Module\ModuleStore):
|
|
* every module, free, bought by the API key or for sale; each with what this
|
|
* panel has installed of it, matched by the store slug.
|
|
*/
|
|
final class ModuleStoreTest extends TestCase {
|
|
private const CATALOGUE = [
|
|
['slug' => 'watch', 'name' => 'Watch Folder', 'version' => '1.2.0', 'price' => 0, 'environment' => 'main', 'xc_vm_compatibility' => '>=2.6.1'],
|
|
['slug' => 'plex-sync', 'name' => 'Plex', 'version' => '2.0.0', 'price' => 19.0, 'environment' => 'main'],
|
|
['slug' => 'epg-pro', 'name' => 'EPG Pro', 'version' => '1.0.0', 'price' => 9.5, 'environment' => 'both'],
|
|
];
|
|
|
|
protected function setUp(): void {
|
|
if (!defined('CACHE_TMP_PATH')) {
|
|
define('CACHE_TMP_PATH', sys_get_temp_dir() . '/xcvm-modstore-' . getmypid() . '/');
|
|
}
|
|
@mkdir(CACHE_TMP_PATH, 0777, true);
|
|
ModuleStore::forget();
|
|
}
|
|
|
|
protected function tearDown(): void {
|
|
ModuleStore::forget();
|
|
}
|
|
|
|
public function testEveryModuleIsListedFreeBoughtOrForSale(): void {
|
|
$rRows = ModuleStore::rows(self::CATALOGUE, ['plex-sync'], []);
|
|
|
|
$this->assertSame(['EPG Pro' => 'paid', 'Plex' => 'purchased', 'Watch Folder' => 'free'], array_column($rRows, 'badge', 'name'));
|
|
$this->assertSame([9.5, 19.0, 0.0], array_column($rRows, 'price'));
|
|
}
|
|
|
|
public function testAnInstalledModuleIsMatchedByItsStoreSlug(): void {
|
|
$rInstalled = [
|
|
['name' => 'watch', 'installed_version' => '1.1.1', 'update' => ['slug' => '']],
|
|
['name' => 'plex', 'installed_version' => '2.0.0', 'update' => ['slug' => 'plex-sync']],
|
|
];
|
|
|
|
$rRows = array_column(ModuleStore::rows(self::CATALOGUE, ['plex-sync'], $rInstalled), null, 'slug');
|
|
|
|
$this->assertSame(['1.1.1', '1.2.0', 'watch'], [$rRows['watch']['installed_version'], $rRows['watch']['update_to'], $rRows['watch']['module']]);
|
|
$this->assertSame(['2.0.0', '', 'plex'], [$rRows['plex-sync']['installed_version'], $rRows['plex-sync']['update_to'], $rRows['plex-sync']['module']]);
|
|
}
|
|
|
|
public function testOwnershipIsAskedOnlyForPaidModulesAndTheAnswerIsCached(): void {
|
|
$rAsked = [];
|
|
$rList = static fn(string $rKey): array => ['ok' => true, 'extensions' => self::CATALOGUE];
|
|
$rCheck = static function (string $rSlug) use (&$rAsked): array {
|
|
$rAsked[] = $rSlug;
|
|
return ['ok' => true, 'allowed' => $rSlug === 'epg-pro'];
|
|
};
|
|
|
|
$rFirst = ModuleStore::catalogue('key-1', false, $rList, $rCheck);
|
|
$rAgain = ModuleStore::catalogue('key-1', false, static fn(): array => ['ok' => false, 'reason' => 'request_failed'], $rCheck);
|
|
|
|
$this->assertSame(['plex-sync', 'epg-pro'], $rAsked);
|
|
$this->assertSame(['epg-pro'], $rFirst['owned']);
|
|
$this->assertSame($rFirst, $rAgain, 'served from the cache');
|
|
}
|
|
|
|
public function testAnotherKeyOrARefreshAsksTheStoreAgain(): void {
|
|
$rCalls = 0;
|
|
$rList = static function () use (&$rCalls): array {
|
|
$rCalls++;
|
|
return ['ok' => true, 'extensions' => []];
|
|
};
|
|
$rCheck = static fn(): array => ['allowed' => false];
|
|
|
|
ModuleStore::catalogue('key-1', false, $rList, $rCheck);
|
|
ModuleStore::catalogue('key-2', false, $rList, $rCheck);
|
|
ModuleStore::catalogue('key-2', true, $rList, $rCheck);
|
|
|
|
$this->assertSame(3, $rCalls);
|
|
}
|
|
|
|
public function testAStoreThatDidNotAnswerIsNotCached(): void {
|
|
$rCheck = static fn(): array => ['allowed' => false];
|
|
|
|
$rFailed = ModuleStore::catalogue('key-1', false, static fn(): array => ['ok' => false, 'reason' => 'request_failed'], $rCheck);
|
|
$rLater = ModuleStore::catalogue('key-1', false, static fn(): array => ['ok' => true, 'extensions' => []], $rCheck);
|
|
|
|
$this->assertSame(['ok' => false, 'reason' => 'request_failed'], $rFailed);
|
|
$this->assertTrue($rLater['ok']);
|
|
}
|
|
|
|
public function testNoApiKeyAsksNothing(): void {
|
|
$this->assertSame(['ok' => false, 'reason' => 'no_api_key'], ModuleStore::catalogue(''));
|
|
}
|
|
}
|