#!/usr/bin/env php 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";