feat(compat): sweep of components against the real core with strict diagnostics
This commit is contained in:
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# Smoke HTTP del paquete cache (APCu sólo existe en SAPI web).
|
||||
set -u
|
||||
|
||||
check() {
|
||||
local comp="$1" path="$2" expect="$3" body
|
||||
if ! body="$(curl -fsS "$BASE$path" 2>/dev/null)"; then
|
||||
echo "$PKG:$comp|fail" >> "$RESULTS"; return
|
||||
fi
|
||||
if printf '%s' "$body" | grep -qF "$expect"; then
|
||||
echo "$PKG:$comp|ok" >> "$RESULTS"
|
||||
else
|
||||
echo " inesperado en $path: $(printf '%s' "$body" | head -c 200)" >&2
|
||||
echo "$PKG:$comp|fail" >> "$RESULTS"
|
||||
fi
|
||||
}
|
||||
|
||||
check apcache /compat/cache/apcache 'APC_OK'
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
// Router de compatibilidad del paquete cache (APCu via SAPI web).
|
||||
|
||||
use Libs\APCache;
|
||||
use Libs\Router;
|
||||
|
||||
Router::get('/compat/cache/apcache', function () {
|
||||
$key = 'compat_' . bin2hex(random_bytes(4));
|
||||
$ok = APCache::save($key, 'valor-42', 30) !== false
|
||||
&& APCache::get($key) === 'valor-42';
|
||||
APCache::delete($key);
|
||||
$ok = $ok && APCache::get($key) === false;
|
||||
echo $ok ? 'APC_OK' : 'APC_FAIL';
|
||||
});
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
# Smoke commands:migration sobre sqlite (flujo CLI real del proyecto).
|
||||
# Recibe BASE, PROJ, PKG, LOG, RESULTS.
|
||||
set -u
|
||||
|
||||
res() { echo "$PKG:$1|$2" >> "$RESULTS"; }
|
||||
|
||||
mkdir -p "$PROJ/migrations"
|
||||
|
||||
cat > "$PROJ/migrations/2026_01_01_000000_compat_demo.php" <<'PHP'
|
||||
<?php
|
||||
|
||||
use Libs\Migration;
|
||||
|
||||
return new class () extends Migration {
|
||||
public function up(): void
|
||||
{
|
||||
$this->create('compat_table', [
|
||||
'id INTEGER PRIMARY KEY AUTOINCREMENT',
|
||||
$this->string('name'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
$this->dropTable('compat_table');
|
||||
}
|
||||
};
|
||||
PHP
|
||||
|
||||
if ! (cd "$PROJ" && php duckbrain migration migrate >"$PROJ/../migrate.out" 2>&1); then
|
||||
echo " migrate fallo:" >&2
|
||||
sed 's/^/ /' "$PROJ/../migrate.out" >&2
|
||||
res migration fail
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PROJ_PATH="$PROJ" php -r '
|
||||
$proj = getenv("PROJ_PATH");
|
||||
$db = new PDO("sqlite:$proj/app.sqlite");
|
||||
$table = (bool) $db->query("SELECT name FROM sqlite_master WHERE type=" . chr(39) . "table" . chr(39) . " AND name=" . chr(39) . "compat_table" . chr(39))->fetchColumn();
|
||||
$ledger = glob("$proj/migrations/migrations-*.sqlite")[0] ?? null;
|
||||
$done = 0;
|
||||
if ($ledger !== null) {
|
||||
$l = new PDO("sqlite:" . $ledger);
|
||||
$done = (int) $l->query("SELECT COUNT(*) FROM migrations")->fetchColumn();
|
||||
}
|
||||
exit($table && $done === 1 ? 0 : 1);' \
|
||||
&& res migration ok \
|
||||
|| { echo " compat_table o registro de migracion ausentes" >&2; res migration fail; }
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# Smoke HTTP del paquete crypto. Recibe BASE, PKG, RESULTS.
|
||||
set -u
|
||||
|
||||
check() {
|
||||
local comp="$1" path="$2" expect="$3" body
|
||||
if ! body="$(curl -fsS "$BASE$path" 2>/dev/null)"; then
|
||||
echo "$PKG:$comp|fail" >> "$RESULTS"; return
|
||||
fi
|
||||
if printf '%s' "$body" | grep -qF "$expect"; then
|
||||
echo "$PKG:$comp|ok" >> "$RESULTS"
|
||||
else
|
||||
echo " inesperado en $path: $(printf '%s' "$body" | head -c 200)" >&2
|
||||
echo "$PKG:$comp|fail" >> "$RESULTS"
|
||||
fi
|
||||
}
|
||||
|
||||
check crypto /compat/crypto/roundtrip 'CRYPTO_OK'
|
||||
check nonce /compat/crypto/nonce 'NONCE_OK'
|
||||
check twoFactor /compat/crypto/2fa 'TFA_OK'
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
// Router de compatibilidad del paquete crypto.
|
||||
|
||||
use Libs\Crypto;
|
||||
use Libs\Nonce;
|
||||
use Libs\Router;
|
||||
use Libs\TwoFactorAuthenticator;
|
||||
|
||||
Router::get('/compat/crypto/roundtrip', function () {
|
||||
$plain = 'secreto: 42 ✓';
|
||||
$hex = Crypto::encryptHex($plain);
|
||||
$b64 = Crypto::encrypt64($plain);
|
||||
$ok = Crypto::decryptHex($hex) === $plain
|
||||
&& Crypto::decrypt64($b64) === $plain
|
||||
&& Crypto::decrypt(Crypto::encrypt($plain)) === $plain;
|
||||
echo $ok ? 'CRYPTO_OK' : 'CRYPTO_MISMATCH';
|
||||
});
|
||||
|
||||
Router::get('/compat/crypto/nonce', function () {
|
||||
$n = Nonce::get('compat');
|
||||
echo (Nonce::check($n, 'compat') && !Nonce::check($n . 'x', 'compat')) ? 'NONCE_OK' : 'NONCE_FAIL';
|
||||
});
|
||||
|
||||
Router::get('/compat/crypto/2fa', function () {
|
||||
$tfa = new TwoFactorAuthenticator();
|
||||
$secret = $tfa->createSecret(16);
|
||||
$code = $tfa->getCode($secret);
|
||||
echo ($tfa->verifyCode($secret, $code, 0) && !$tfa->verifyCode($secret, '000000', 0)) ? 'TFA_OK' : 'TFA_FAIL';
|
||||
});
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
# Smoke HTTP del paquete htmx. Recibe BASE, PKG, RESULTS.
|
||||
set -u
|
||||
|
||||
check() {
|
||||
local comp="$1" path="$2" expect="$3" body
|
||||
if ! body="$(curl -fsS "$BASE$path" 2>/dev/null)"; then
|
||||
echo "$PKG:$comp|fail" >> "$RESULTS"; return
|
||||
fi
|
||||
if printf '%s' "$body" | grep -qF "$expect"; then
|
||||
echo "$PKG:$comp|ok" >> "$RESULTS"
|
||||
else
|
||||
echo " inesperado en $path: $(printf '%s' "$body" | head -c 200)" >&2
|
||||
echo "$PKG:$comp|fail" >> "$RESULTS"
|
||||
fi
|
||||
}
|
||||
|
||||
check htmlComponent /compat/htmx/render '<h1 id="compat-greet">A<b></h1>'
|
||||
check htmx /compat/htmx/static 'HTMX:false:true'
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
// Router de compatibilidad del paquete htmx: monta un componente propio sobre
|
||||
// el motor HTMLComponent/HTMX con el arranque real del core.
|
||||
|
||||
use Libs\HTMLComponent;
|
||||
use Libs\HTMX;
|
||||
use Libs\Router;
|
||||
|
||||
$views = ROOT_CORE . '/Views';
|
||||
if (!is_dir($views)) {
|
||||
mkdir($views, 0777, true);
|
||||
}
|
||||
|
||||
file_put_contents($views . '/CompatGreet.php', <<<'VIEW'
|
||||
<h1 id="compat-greet"><?php echo $this->escapedProperty('name'); ?></h1>
|
||||
VIEW);
|
||||
|
||||
file_put_contents($views . '/CompatButton.php', <<<'VIEW'
|
||||
<button hx-post="/compat/htmx/echo" hx-target="#compat-greet" class="btn">ir</button>
|
||||
VIEW);
|
||||
|
||||
Router::get('/compat/htmx/render', function () {
|
||||
echo 'GREET:';
|
||||
HTMLComponent::render('CompatGreet', ['name' => 'A<b>']);
|
||||
});
|
||||
|
||||
Router::get('/compat/htmx/static', function () {
|
||||
$instance = new HTMX([], '<i hx-get="/x">ok</i>');
|
||||
header('X-Marker: ' . (HTMX::isHtmx() ? 'yes' : 'no'));
|
||||
echo 'HTMX:' . var_export(HTMX::isPartialRequest(), true)
|
||||
. ':' . var_export($instance->getContent() !== '', true);
|
||||
});
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
# Smoke del paquete http. Recibe BASE, PKG, RESULTS.
|
||||
set -u
|
||||
|
||||
check() {
|
||||
local comp="$1" path="$2" expect="$3" body
|
||||
if ! body="$(curl -fsS "$BASE$path" 2>/dev/null)"; then
|
||||
echo "$PKG:$comp|fail" >> "$RESULTS"; return
|
||||
fi
|
||||
if printf '%s' "$body" | grep -qF "$expect"; then
|
||||
echo "$PKG:$comp|ok" >> "$RESULTS"
|
||||
else
|
||||
echo " inesperado en $path: $(printf '%s' "$body" | head -c 200)" >&2
|
||||
echo "$PKG:$comp|fail" >> "$RESULTS"
|
||||
fi
|
||||
}
|
||||
|
||||
check curlRequest /compat/http/curl 'CURL_OK'
|
||||
check aria2 '/compat/http/load?class=Aria2' 'LOAD_OK:Libs\Aria2'
|
||||
check proxy '/compat/http/load?class=Proxy' 'LOAD_OK:Libs\Proxy'
|
||||
check compreFace '/compat/http/load?class=CompreFace' 'LOAD_OK:Libs\CompreFace'
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
// Router de compatibilidad del paquete http: curlRequest con flujo completo
|
||||
// (se llama a si mismo via el mismo servidor) y carga nivel 1 de los clientes
|
||||
// con servicio externo.
|
||||
|
||||
use Libs\Aria2;
|
||||
use Libs\CompreFace;
|
||||
use Libs\CurlRequest;
|
||||
use Libs\Proxy;
|
||||
use Libs\Router;
|
||||
|
||||
Router::get('/compat/http/echo', function () {
|
||||
echo 'ECHO:' . ($_GET['who'] ?? 'nadie');
|
||||
});
|
||||
|
||||
Router::get('/compat/http/curl', function () {
|
||||
$host = $_SERVER['HTTP_HOST'];
|
||||
$req = new CurlRequest();
|
||||
$req->get("http://$host/compat/http/echo?who=42");
|
||||
echo str_contains($req->body(), 'ECHO:42') ? 'CURL_OK' : 'CURL_FAIL:' . substr($req->body(), 0, 80);
|
||||
});
|
||||
|
||||
Router::get('/compat/http/load', function () {
|
||||
$class = 'Libs\\' . basename((string) ($_GET['class'] ?? ''));
|
||||
if (!class_exists($class)) {
|
||||
echo 'LOAD_MISSING';
|
||||
return;
|
||||
}
|
||||
$instance = match ($class) {
|
||||
'Libs\\Aria2' => new Aria2('http://127.0.0.1:6800/jsonrpc'),
|
||||
'Libs\\CompreFace' => new CompreFace('compat-key', 'http://127.0.0.1:18080'),
|
||||
default => new $class(),
|
||||
};
|
||||
echo 'LOAD_OK:' . get_class($instance);
|
||||
});
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# Smoke HTTP del paquete id. Recibe BASE, PKG, RESULTS.
|
||||
set -u
|
||||
|
||||
check() {
|
||||
local comp="$1" path="$2" expect="$3" body
|
||||
if ! body="$(curl -fsS "$BASE$path" 2>/dev/null)"; then
|
||||
echo "$PKG:$comp|fail" >> "$RESULTS"; return
|
||||
fi
|
||||
if printf '%s' "$body" | grep -qF "$expect"; then
|
||||
echo "$PKG:$comp|ok" >> "$RESULTS"
|
||||
else
|
||||
echo " inesperado en $path: $(printf '%s' "$body" | head -c 200)" >&2
|
||||
echo "$PKG:$comp|fail" >> "$RESULTS"
|
||||
fi
|
||||
}
|
||||
|
||||
check ulid /compat/id/ulid 'ULID_OK'
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
// Router de compatibilidad del paquete id.
|
||||
|
||||
use Libs\Router;
|
||||
use Libs\Ulid;
|
||||
|
||||
Router::get('/compat/id/ulid', function () {
|
||||
$a = Ulid::generate();
|
||||
$b = Ulid::generate();
|
||||
$ok = strlen($a) === 26 && Ulid::validate($a) && !Ulid::validate(str_repeat('0', 25)) && $a !== $b;
|
||||
echo $ok ? 'ULID_OK' : 'ULID_FAIL';
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"text": {
|
||||
"filter": "full",
|
||||
"replacement": "full"
|
||||
},
|
||||
"crypto": {
|
||||
"crypto": "full",
|
||||
"nonce": "full",
|
||||
"twoFactor": "full"
|
||||
},
|
||||
"id": {
|
||||
"ulid": "full"
|
||||
},
|
||||
"cache": {
|
||||
"apcache": "full"
|
||||
},
|
||||
"htmx": {
|
||||
"htmlComponent": "full",
|
||||
"htmx": "full"
|
||||
},
|
||||
"http": {
|
||||
"curlRequest": "full",
|
||||
"aria2": "load",
|
||||
"proxy": "load",
|
||||
"compreFace": "load"
|
||||
},
|
||||
"commands": {
|
||||
"migration": "sqlite",
|
||||
"cli": { "level": "none", "reason": "es el CLI del instalador; no consume el core (evidencia: suite offline group7/8)" },
|
||||
"toolbox": { "level": "none", "reason": "motor del instalador; no consume el core (evidencia: suite offline group7/8)" }
|
||||
},
|
||||
"test": {
|
||||
"harness": "runner"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"core": {
|
||||
"version": "0.1.0",
|
||||
"commit": "3b6da45b019d0c232bb5b2f1dc158d2bf25c8e1b"
|
||||
},
|
||||
"generated": "2026-10-05T20:34:25Z",
|
||||
"components": {
|
||||
"text:filter": {
|
||||
"status": "ok",
|
||||
"level": "full"
|
||||
},
|
||||
"text:replacement": {
|
||||
"status": "ok",
|
||||
"level": "full"
|
||||
},
|
||||
"crypto:crypto": {
|
||||
"status": "ok",
|
||||
"level": "full"
|
||||
},
|
||||
"crypto:nonce": {
|
||||
"status": "ok",
|
||||
"level": "full"
|
||||
},
|
||||
"crypto:twoFactor": {
|
||||
"status": "ok",
|
||||
"level": "full"
|
||||
},
|
||||
"id:ulid": {
|
||||
"status": "ok",
|
||||
"level": "full"
|
||||
},
|
||||
"cache:apcache": {
|
||||
"status": "ok",
|
||||
"level": "full"
|
||||
},
|
||||
"htmx:htmlComponent": {
|
||||
"status": "ok",
|
||||
"level": "full"
|
||||
},
|
||||
"htmx:htmx": {
|
||||
"status": "ok",
|
||||
"level": "full"
|
||||
},
|
||||
"http:curlRequest": {
|
||||
"status": "ok",
|
||||
"level": "full"
|
||||
},
|
||||
"http:aria2": {
|
||||
"status": "ok",
|
||||
"level": "load"
|
||||
},
|
||||
"http:proxy": {
|
||||
"status": "ok",
|
||||
"level": "load"
|
||||
},
|
||||
"http:compreFace": {
|
||||
"status": "ok",
|
||||
"level": "load"
|
||||
},
|
||||
"commands:migration": {
|
||||
"status": "ok",
|
||||
"level": "sqlite"
|
||||
},
|
||||
"commands:cli": {
|
||||
"status": "skipped",
|
||||
"level": "none",
|
||||
"reason": "es el CLI del instalador; no consume el core (evidencia: suite offline group7/8)"
|
||||
},
|
||||
"commands:toolbox": {
|
||||
"status": "skipped",
|
||||
"level": "none",
|
||||
"reason": "motor del instalador; no consume el core (evidencia: suite offline group7/8)"
|
||||
},
|
||||
"test:harness": {
|
||||
"status": "ok",
|
||||
"level": "runner"
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
# Smoke test:harness — runner real (phpunit via composer) en el proyecto temporal.
|
||||
# Recibe PROJ, PKG, RESULTS.
|
||||
set -u
|
||||
|
||||
res() { echo "$PKG:harness|$1" >> "$RESULTS"; }
|
||||
|
||||
cd "$PROJ" || { res fail; exit 0; }
|
||||
|
||||
if [ ! -f composer.json ]; then
|
||||
printf '{"name":"duckbrain/compat-probe","require":{}}\n' > composer.json
|
||||
fi
|
||||
|
||||
if ! COMPOSER_NO_INTERACTION=1 composer require --dev phpunit/phpunit:^11.0 fakerphp/faker \
|
||||
--no-interaction >/dev/null 2>"$PROJ/../composer.err"; then
|
||||
echo " composer require fallo:" >&2
|
||||
sed 's/^/ /' "$PROJ/../composer.err" >&2
|
||||
res fail
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! ./vendor/bin/phpunit >/dev/null 2>"$PROJ/../phpunit.err"; then
|
||||
echo " phpunit fallo:" >&2
|
||||
sed 's/^/ /' "$PROJ/../phpunit.err" >&2
|
||||
res fail
|
||||
exit 0
|
||||
fi
|
||||
|
||||
res ok
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# Smoke HTTP del paquete text. Recibe BASE, PROJ, PKG, LOG, RESULTS.
|
||||
set -u
|
||||
|
||||
check() {
|
||||
local comp="$1" path="$2" expect="$3" body
|
||||
if ! body="$(curl -fsS "$BASE$path" 2>/dev/null)"; then
|
||||
echo "$PKG:$comp|fail" >> "$RESULTS"
|
||||
return
|
||||
fi
|
||||
if printf '%s' "$body" | grep -qF "$expect"; then
|
||||
echo "$PKG:$comp|ok" >> "$RESULTS"
|
||||
else
|
||||
echo " respuesta inesperada en $path: $(printf '%s' "$body" | head -c 200)" >&2
|
||||
echo "$PKG:$comp|fail" >> "$RESULTS"
|
||||
fi
|
||||
}
|
||||
|
||||
check filter /compat/text/filter 'HOLA MUNDIN'
|
||||
check replacement /compat/text/replacement 'bar y food'
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
// Router de compatibilidad del paquete text (inyectado en src/Routers/Compat.php
|
||||
// por scripts/compat-sweep). Ejercita Filter y Replacement sobre el arranque
|
||||
// real del core (Loader -> Router::apply()).
|
||||
|
||||
use Libs\Filter;
|
||||
use Libs\Replacement;
|
||||
use Libs\Router;
|
||||
|
||||
Router::get('/compat/text/filter', function () {
|
||||
Filter::add(
|
||||
fn (string $content): string => str_replace('mundo', 'MUNDIN', $content),
|
||||
'compat',
|
||||
5
|
||||
);
|
||||
Filter::add(
|
||||
fn (string $content): string => strtoupper($content) . '|',
|
||||
'compat',
|
||||
20
|
||||
);
|
||||
echo 'FILTER_OK:' . Filter::apply('hola mundo', 'compat');
|
||||
});
|
||||
|
||||
Router::get('/compat/text/replacement', function () {
|
||||
Replacement::add('/\bfoo\b/', 'bar');
|
||||
echo 'REPL_OK:' . Replacement::apply('foo y food y foo');
|
||||
});
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
use Toolbox\Catalog;
|
||||
|
||||
Harness::suite('group11-compat');
|
||||
|
||||
$GLOBALS['g11_repo'] = dirname(__DIR__);
|
||||
|
||||
/**
|
||||
* Contratos:
|
||||
* - levels.json debe cubrir exactamente los componentes del catalogo.
|
||||
* - si tests/compat/report.json existe, todo 'tested' declarado debe estar
|
||||
* respaldado por un 'ok' del reporte, y los niveles 'none' no deben
|
||||
* declarar tested.
|
||||
* Sin reporte (entorno offline sin haber corrido el barrido) solo se exige el
|
||||
* primer contrato.
|
||||
*/
|
||||
Harness::it('levels.json cubre exactamente los componentes del catalogo', function () {
|
||||
$repo = $GLOBALS['g11_repo'];
|
||||
$levels = json_decode((string) file_get_contents($repo . '/tests/compat/levels.json'), true);
|
||||
ok(is_array($levels), 'levels.json debe ser un objeto por paquete');
|
||||
|
||||
$catalog = Catalog::fromRoot($repo);
|
||||
$declared = [];
|
||||
foreach ($catalog->packages() as $manifest) {
|
||||
foreach (array_keys($manifest->components()) as $component) {
|
||||
$declared[] = $manifest->name . ':' . $component;
|
||||
}
|
||||
}
|
||||
|
||||
$planned = [];
|
||||
foreach ($levels as $package => $components) {
|
||||
foreach (array_keys($components) as $component) {
|
||||
$planned[] = $package . ':' . $component;
|
||||
}
|
||||
}
|
||||
|
||||
sort($declared);
|
||||
sort($planned);
|
||||
eq($declared, $planned, 'cada componente del catalogo tiene su nivel de evidencia planeado');
|
||||
});
|
||||
|
||||
Harness::it('los stamps tested estan respaldados por el reporte del barrido', function () {
|
||||
$repo = $GLOBALS['g11_repo'];
|
||||
$reportPath = $repo . '/tests/compat/report.json';
|
||||
|
||||
if (!is_file($reportPath)) {
|
||||
return; // offline sin barrido previo: no se inventa evidencia ni se exige.
|
||||
}
|
||||
|
||||
$report = json_decode((string) file_get_contents($reportPath), true);
|
||||
ok(is_array($report) && isset($report['components']), 'report.json valido');
|
||||
|
||||
$levels = json_decode((string) file_get_contents($repo . '/tests/compat/levels.json'), true);
|
||||
$catalog = Catalog::fromRoot($repo);
|
||||
|
||||
foreach ($catalog->packages() as $manifest) {
|
||||
foreach (array_keys($manifest->components()) as $component) {
|
||||
$id = $manifest->name . ':' . $component;
|
||||
$level = $levels[$manifest->name][$component] ?? null;
|
||||
$level = is_array($level) ? $level['level'] : $level;
|
||||
$status = $report['components'][$id]['status'] ?? 'missing';
|
||||
$tested = $manifest->testedCore($component);
|
||||
|
||||
if ($level === 'none') {
|
||||
eq(null, $tested, "$id esta deliberadamente sin datos y no debe declarar tested");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($tested !== null) {
|
||||
eq('ok', $status, "$id declara tested='$tested' pero su evidencia en el reporte es '$status'");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user