*/ private array $options = []; protected function setUp(): void { parent::setUp(); $this->options = []; Functions\when('get_option')->alias(fn (string $name, mixed $default = false): mixed => $this->options[$name] ?? $default); Functions\when('update_option')->alias(function (string $name, mixed $value, mixed $autoload = null): bool { self::assertFalse($autoload, 'snapshots are never autoloaded'); $this->options[$name] = $value; return true; }); Functions\when('get_current_user_id')->justReturn(7); } public function testSavesListsAndReturnsTheNewestFirst(): void { $store = new SnapshotStore(); $first = $store->save('presets', ['module' => ['a' => 1]], 'lit/divi-presets-set'); $second = $store->save('presets', ['module' => ['a' => 2]], 'lit/divi-presets-set'); $store->attachLog('presets', $second, 42); self::assertSame('lit_mcp_snapshots_presets', SnapshotStore::option('presets')); self::assertMatchesRegularExpression('/^presets-\d{8}T\d{6}Z-[0-9a-f]{6}$/', $first); $list = $store->list('presets'); self::assertSame([$second, $first], array_column($list, 'id')); self::assertSame(42, $list[0]['log_id']); self::assertSame(7, $list[0]['user_id']); self::assertArrayNotHasKey('data', $list[0]); self::assertSame(['module' => ['a' => 1]], $store->get('presets', $first)['data']); self::assertNull($store->get('presets', 'presets-unknown')); self::assertSame([], $store->list('colors')); } public function testKeepsAtMostTwentyPerArea(): void { $store = new SnapshotStore(); $ids = []; for ($i = 0; $i < 22; ++$i) { $ids[] = $store->save('presets', ['n' => $i], 'lit/divi-presets-set'); } $list = $store->list('presets'); self::assertCount(SnapshotStore::LIMIT, $list); self::assertSame($ids[21], $list[0]['id']); self::assertNull($store->get('presets', $ids[0])); self::assertNull($store->get('presets', $ids[1])); } public function testRefusesSnapshotsAboveTheLimit(): void { $this->expectException(SnapshotTooLarge::class); (new SnapshotStore())->save('presets', ['x' => str_repeat('a', SnapshotStore::MAX_BYTES)], 'lit/divi-presets-set'); } public function testUnknownAreaIsAProgrammingError(): void { $this->expectException(InvalidArgumentException::class); SnapshotStore::option('pages'); } public function testAFailedOptionWriteThrows(): void { Functions\when('update_option')->justReturn(false); $this->expectException(RuntimeException::class); $this->expectExceptionMessage('snapshot presets could not be stored'); (new SnapshotStore())->save('presets', ['a' => 1], 'lit/divi-presets-set'); } public function testCorruptOptionReadsAsEmpty(): void { $this->options['lit_mcp_snapshots_presets'] = 'kaputt'; self::assertSame([], (new SnapshotStore())->list('presets')); } }