test(api): lock MiniMax config redaction + isSet contract (#358)

Regression coverage for the read-side shape that the frontend `ConfigurationXLVask.refreshMiniMaxApiKeyStatus` parses. Mirrors `BirdConfigSecretRedactionTest` — locks the contract that `api_key` is redacted with `isSet` reflecting actual persistence, so the XL Vask autopilot's `requireModuleEnabled` cannot silently break on a regression.

No production-code change — backend already correct (verified live 2026-08-10 07:58 against `api-v2.truckwash.io` with both `{variable, value}` and raw-key payload shapes).

Companion pleno-vue PR: #281 ("fix(pleno-vue): persist MiniMax API key across refresh + render fix").
This commit is contained in:
Jeppe B
2026-08-10 08:45:10 +02:00
committed by GitHub
parent 801c8e1f6d
commit 2ef0f78541
@@ -0,0 +1,131 @@
<?php
app_require('traits/module_config_t.php');
use traits\module_config_t;
if (!class_exists('MiniMaxSecretConfigDefinitionStub')) {
class MiniMaxSecretConfigDefinitionStub
{
public bool $config_variable_is_secret = true;
public function getVariableName(): string
{
return 'api_key';
}
}
}
if (!class_exists('MiniMaxBoolConfigDefinitionStub')) {
class MiniMaxBoolConfigDefinitionStub
{
public bool $config_variable_is_secret = false;
public function getVariableName(): string
{
return 'enabled';
}
}
}
if (!class_exists('MiniMaxModuleConfigRedactionHarness')) {
class MiniMaxModuleConfigRedactionHarness
{
use module_config_t;
public function __construct()
{
$this->config_classes = [
MiniMaxSecretConfigDefinitionStub::class,
MiniMaxBoolConfigDefinitionStub::class,
];
}
public function extract(object $db): array
{
return $this->extracted($db, 'SELECT test');
}
}
}
it('redacts configured MiniMax secrets while preserving isSet metadata', function (): void {
$rows = [
['module' => 'miniMax', 'variable' => 'api_key', 'type' => 'string', 'value' => 'never-return-this'],
['module' => 'miniMax', 'variable' => 'enabled', 'type' => 'bool', 'value' => 'true'],
];
$result = new class($rows) {
public function __construct(private array $rows)
{
}
public function fetch_assoc(): ?array
{
return array_shift($this->rows);
}
};
$db = new class($result) {
public function __construct(private object $result)
{
}
public function query(string $sql): object
{
return $this->result;
}
};
$config = (new MiniMaxModuleConfigRedactionHarness())->extract($db);
expect($config[0])->toMatchArray([
'module' => 'miniMax',
'variable' => 'api_key',
'type' => 'string',
'value' => '[redacted]',
'isSecret' => true,
'isSet' => true,
])->and($config[1])->toMatchArray([
'module' => 'miniMax',
'variable' => 'enabled',
'type' => 'bool',
'value' => true,
'isSecret' => false,
'isSet' => true,
]);
});
it('reports isSet=false when the stored MiniMax api_key is empty', function (): void {
$rows = [
['module' => 'miniMax', 'variable' => 'api_key', 'type' => 'string', 'value' => ''],
];
$result = new class($rows) {
public function __construct(private array $rows)
{
}
public function fetch_assoc(): ?array
{
return array_shift($this->rows);
}
};
$db = new class($result) {
public function __construct(private object $result)
{
}
public function query(string $sql): object
{
return $this->result;
}
};
$config = (new MiniMaxModuleConfigRedactionHarness())->extract($db);
expect($config[0])->toMatchArray([
'module' => 'miniMax',
'variable' => 'api_key',
'type' => 'string',
'value' => '',
'isSecret' => true,
'isSet' => false,
]);
});