109 lines
4.6 KiB
PHP
Executable File
109 lines
4.6 KiB
PHP
Executable File
#!/usr/bin/env php
|
|
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
function assert_true(bool $cond, string $msg): void
|
|
{
|
|
if (!$cond) {
|
|
fwrite(STDERR, "[FAIL] {$msg}\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
function request(string $method, string $route, array $json = [], array $headers = []): array|WP_Error
|
|
{
|
|
$req = new WP_REST_Request($method, $route, $json, $headers);
|
|
return rest_do_request($req);
|
|
}
|
|
|
|
function unwrap(array|WP_Error $res, string $context): array
|
|
{
|
|
if ($res instanceof WP_Error) {
|
|
$status = $res->data['status'] ?? 500;
|
|
fwrite(STDERR, "[FAIL] {$context}: {$res->code} {$res->message} ({$status})\n");
|
|
exit(1);
|
|
}
|
|
return $res;
|
|
}
|
|
|
|
require __DIR__ . '/wp_emulation.php';
|
|
|
|
$html = do_shortcode('[calendar]');
|
|
assert_true(str_contains($html, 'cp-login-btn'), 'calendar shortcode should render login button');
|
|
assert_true(str_contains($html, 'cp-create-btn'), 'calendar shortcode should render create button');
|
|
assert_true(str_contains($html, 'cp-public-list'), 'calendar shortcode should render public list');
|
|
assert_true(str_contains($html, 'cp-verify-btn'), 'calendar shortcode should render verify action');
|
|
assert_true(str_contains($html, 'cp-reset-request-btn'), 'calendar shortcode should render reset action');
|
|
assert_true(str_contains($html, 'cp-future-only'), 'calendar shortcode should render future-only control');
|
|
assert_true(str_contains($html, 'cp-theme'), 'calendar shortcode should render theme selector');
|
|
assert_true(str_contains($html, 'cp-delete-occ-confirm-btn'), 'calendar shortcode should render delete occurrence control');
|
|
|
|
$reg = unwrap(request('POST', '/calendar/v1/users/register', [
|
|
'email' => 'ui-emu@example.test',
|
|
'password' => 'pass12345',
|
|
'debug_tokens' => true,
|
|
]), 'register');
|
|
$verify = (string) ($reg['data']['verify_token'] ?? '');
|
|
$userId = (int) ($reg['data']['user']['id'] ?? 0);
|
|
assert_true($verify !== '' && $userId > 0, 'registration should provide token/id in debug mode');
|
|
|
|
unwrap(request('POST', '/calendar/v1/users/verify', ['token' => $verify]), 'verify');
|
|
unwrap(request('PATCH', '/calendar/v1/admin/users/' . $userId . '/approve', []), 'approve');
|
|
|
|
$GLOBALS['wp_user'] = [
|
|
'id' => 0,
|
|
'email' => '',
|
|
'caps' => [],
|
|
];
|
|
|
|
$authHeader = 'Basic ' . base64_encode('ui-emu@example.test:pass12345');
|
|
$me = unwrap(request('GET', '/calendar/v1/users/me', [], ['Authorization' => $authHeader]), 'users me');
|
|
assert_true((string) ($me['data']['email'] ?? '') === 'ui-emu@example.test', 'me endpoint should resolve basic user');
|
|
|
|
$created = unwrap(request('POST', '/calendar/v1/events', [
|
|
'title' => 'UI Emu Event',
|
|
'description' => 'ui flow',
|
|
'location' => 'Desk',
|
|
'category' => 'Test',
|
|
'all_day_event' => false,
|
|
'start_datetime' => '2026-06-01T10:00:00+01:00',
|
|
'end_datetime' => '2026-06-01T11:00:00+01:00',
|
|
'repeat_type' => 'daily',
|
|
'repeat_interval' => 1,
|
|
'repeat_range_mode' => 'count',
|
|
'repeat_count' => 3,
|
|
], ['Authorization' => $authHeader]), 'create event');
|
|
$eventId = (int) ($created['data']['id'] ?? 0);
|
|
assert_true($eventId > 0, 'basic-auth user should be able to create event');
|
|
|
|
unwrap(request('DELETE', '/calendar/v1/events/' . $eventId . '/occurrences/' . rawurlencode('2026-06-02T10:00:00+01:00'), [], ['Authorization' => $authHeader]), 'delete occurrence');
|
|
$occ = unwrap(request('GET', '/calendar/v1/events/' . $eventId . '/occurrences', ['from' => '2026-06-01', 'months' => 1], ['Authorization' => $authHeader]), 'list occurrences');
|
|
$days = [];
|
|
foreach ((array) ($occ['data'] ?? []) as $row) {
|
|
$days[] = substr((string) ($row['occurrence_start'] ?? ''), 0, 10);
|
|
}
|
|
assert_true(!in_array('2026-06-02', $days, true), 'deleted occurrence should not remain');
|
|
|
|
unwrap(request('DELETE', '/calendar/v1/events/' . $eventId, [], ['Authorization' => $authHeader]), 'delete event');
|
|
$deletedEvent = request('GET', '/calendar/v1/events/' . $eventId, [], ['Authorization' => $authHeader]);
|
|
assert_true($deletedEvent instanceof WP_Error, 'deleted event should not resolve');
|
|
assert_true(($deletedEvent->data['status'] ?? 0) === 404, 'deleted event fetch should return 404');
|
|
|
|
$GLOBALS['wp_user'] = [
|
|
'id' => 1,
|
|
'email' => 'admin@example.test',
|
|
'caps' => ['manage_options', 'edit_posts'],
|
|
];
|
|
unwrap(request('DELETE', '/calendar/v1/admin/users/' . $userId, []), 'remove user');
|
|
$GLOBALS['wp_user'] = [
|
|
'id' => 0,
|
|
'email' => '',
|
|
'caps' => [],
|
|
];
|
|
$meAfterRemove = request('GET', '/calendar/v1/users/me', [], ['Authorization' => $authHeader]);
|
|
assert_true($meAfterRemove instanceof WP_Error, 'removed user should not authenticate');
|
|
assert_true(($meAfterRemove->data['status'] ?? 0) === 401, 'removed user me endpoint should return 401');
|
|
|
|
echo "[PASS] ui-e2e wp emulation\n";
|