Files
preland/admin/tests/part.php
T

37 lines
3.4 KiB
PHP

<?php
/** api#347: общий редактор, копирование и старое приватное состояние. */
declare(strict_types=1);
require dirname(__DIR__).'/bootstrap.php';
use PrelandAdmin\{Config,Copy,LinkBuilder,Notes,Store,Problem};
function partCheck(bool $ok,string $message): void {if(!$ok)throw new RuntimeException($message);echo "PASS $message\n";}
$valid=Config::decode('{"host":"keep.example","metadata":{"keep":true},"utm":{"part":{"default":"2","weights":{"1":0,"2":100}},"unknown":{"keep":true}}}');
Config::validate($valid);
foreach (['{"default":"3","weights":{}}','{"default":"1","weights":{"9":1}}','{"default":"1","weights":{"2":-1}}','{"default":"1","weights":{"1":1}}'] as $group) {
$invalid=Config::decode('{"utm":{"part":'.$group.'}}');$rejected=false;
try {Config::validate($invalid);}catch(Problem){$rejected=true;}
partCheck($rejected,'invalid part enum/weights rejected');
}
$project=new ReflectionMethod(Copy::class,'project');$changes=$project->invoke(null,$valid);
$target=Config::decode('{"host":"before.example","notes":"keep","utm":{"part":{"default":"1","weights":{"1":1},"metadata":"keep"},"unknown":{"keep":true}}}');
$patched=Config::patch($target,$changes);
partCheck($patched->utm->part->default==='2'&&$patched->utm->part->weights->{'2'}===100,'copy includes part default and weights');
partCheck($patched->host==='before.example'&&$patched->notes==='keep'&&$patched->utm->part->metadata==='keep'&&$patched->utm->unknown->keep===true,'copy preserves metadata and unknown groups');
$root=sys_get_temp_dir().'/part347-'.bin2hex(random_bytes(6));$store=new Store($root);
$notes=new Notes($store);$old=$notes->all();unset($old['part']);$store->write('utm-notes.json',$old);
$loaded=$notes->all();partCheck(isset($loaded['part'])&&array_diff_key($loaded,['part'=>true])===$old,'old notes gain empty part without losing notes/versions');
$notes->save(['marker'=>'part','text'=>'Видимость ссылки на сайте','version'=>$loaded['part']['version']]);
partCheck($notes->all()['part']['text']==='Видимость ссылки на сайте','part note saves with CAS');
$store->write('targets.json',['fixture'=>['id'=>'fixture','domain'=>'fixture.example']]);
$oldSelection=['indpic'=>'1','theme'=>'1','degr'=>'1','reg'=>'2','banch'=>'2','tp'=>'1','cons'=>'2','focus'=>'1'];
$params=[];foreach($oldSelection as $key=>$value)$params[$key]='abcd'.$value.'abcdefabcdef';
$store->write('link-builder-fixture.json',['selection'=>$oldSelection,'url'=>'https://fixture.example/?'.http_build_query($params),'saved_at'=>'2026-10-28T01:00:00+00:00']);
$builder=new LinkBuilder($store);$saved=$builder->get('fixture');
partCheck($saved['selection']===$oldSelection+['part'=>'1'],'old saved builder choice gains default1');
parse_str(parse_url($saved['url'],PHP_URL_QUERY),$newParams);
partCheck(array_intersect_key($newParams,$params)===$params&&$newParams['part'][4]==='1','migration preserves old noise and adds masked part');
partCheck($builder->get('fixture')===$saved,'migrated builder reload preserves exact noise');
foreach(['1','2','rnd'] as $part)partCheck($builder->save('fixture',array_replace($saved['selection'],['part'=>$part]))['selection']['part']===$part,'builder supports part '.$part);
try{$builder->save('fixture',array_replace($saved['selection'],['part'=>'3']));throw new RuntimeException('invalid builder part accepted');}catch(Problem){}
echo "Part admin contract complete\n";