Skip to content

Conversation

@tobixen
Copy link
Member

@tobixen tobixen commented Nov 27, 2025

No description provided.

tobixen and others added 4 commits November 23, 2025 20:13
Add 14 integration-style tests that demonstrate mocking CalDAV server
responses for testing check classes without actual server communication.

Tests added:
- TestCheckGetCurrentUserPrincipal: 3 tests for principal detection
- TestCheckMakeDeleteCalendar: 5 tests (2 passing, 3 skipped due to complexity)
- TestPrepareCalendar: 3 tests for calendar preparation and data setup
- TestCheckSearch: 6 tests for search functionality with various scenarios

Key features:
- All tests use unittest.mock to simulate server responses
- Tests demonstrate patterns for mocking caldav library objects
- Complex multi-retry test scenarios are marked as skipped with explanations
- Tests marked as "slow" (can be excluded with `pytest -m "not slow"`)

Test execution times:
- Fast unit tests (test_ai_*.py): 54 tests in ~1.2s
- Slow mocked tests (test_checks_with_mocks.py): 14 tests in ~70s (due to running actual check logic)
- Total: 68 passed, 3 skipped

Configuration:
- Added pytest marker configuration for "slow" tests
- Run fast tests only with: pytest -m "not slow"
- Run all tests with: pytest

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The test was failing because the mock wasn't properly tracking calendar
lifecycle. The pre-cleanup delete() at line 96 in checks.py was setting
the deleted flag before the test calendar was even created, causing
events() calls to fail prematurely.

Solution: Track both created and deleted states separately. Only mark as
deleted when delete() is called on an actually-created calendar.

Also fixed some issues in checks.py:
- Import DAVError for proper exception handling
- Replace broad Exception catches with specific DAVError
- Fix condition at line 147 to use features_checked.is_supported()

All 68 tests now pass (3 skipped).

Note: The mocked integration tests have questionable value as they're
tightly coupled to implementation details. They may be removed in the
future if they become a maintenance burden. The unit tests provide
better value for rapid development feedback.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Apparently Zimbra will now delete the RRULE property from a task if count is set.  For the symmetry, I added a save-load.event.recurrences as well (Zimbra passes that one).
This commit enhances the CalDAV search functionality testing and improves
test maintainability:

## Search Test Improvements
- Add SearchMixIn class with search_find_set() helper method to reduce
  boilerplate in search feature testing
- Expand search feature coverage:
  - Text search (case-sensitive, case-insensitive, substring)
  - Property filter with CalDAVSearcher (is-not-defined operator)
  - Category search and substring matching
  - Combined search filters (logical AND behavior)
- Add post_filter=False to all server behavior tests to ensure we're
  testing actual server responses, not client-side filtering
- Improve comp-type-optional test with additional text search validation
- Add test event without summary property to validate optional fields

## Test Maintenance
- Remove test_ai_checks_with_mocks.py - these AI-generated mocked tests
  were fragile and difficult to maintain. The file itself documented
  that it should be deleted if it breaks. All meaningful test coverage
  is provided by the remaining unit tests.

## Bug Fixes
- Fix create-calendar feature detection to not mark mkcol method as
  standard calendar creation
- Capitalize event summary to match actual test data

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
tobixen and others added 23 commits November 29, 2025 11:38
This commit enhances the CalDAV search functionality testing and improves
test maintainability:

## Search Test Improvements
- Add SearchMixIn class with search_find_set() helper method to reduce
  boilerplate in search feature testing
- Expand search feature coverage with new feature flags:
  - search.text - Basic text/summary search
  - search.text.case-sensitive - Case-sensitive text matching (default)
  - search.text.case-insensitive - Case-insensitive via CalDAVSearcher
  - search.text.substring - Substring matching for text searches
  - search.is-not-defined - Property filter with is-not-defined operator
  - search.text.category - Category search support
  - search.text.category.substring - Substring matching for categories
- Add post_filter=False to all server behavior tests to ensure we're
  testing actual server responses, not client-side filtering
- Improve search.comp-type-optional test with additional text search validation
- Add test event without summary property to validate optional fields

## Test Maintenance
- Remove test_ai_checks_with_mocks.py - these AI-generated mocked tests
  were fragile and difficult to maintain. The file itself documented
  that it should be deleted if it breaks. All meaningful test coverage
  is provided by the remaining unit tests.

## Bug Fixes
- Fix create-calendar feature detection to not mark mkcol method as
  standard calendar creation
- Capitalize event summary to match actual test data

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Implements comprehensive checks for RFC6578 sync-collection reports:
- Detects if server supports sync tokens at all
- Identifies time-based tokens (second-precision, requires sleep(1))
- Detects fragile implementations (extra content from race conditions)
- Tests sync support after object deletion

New features:
- sync-token: support levels (full/fragile/unsupported) with behaviour flag
- sync-token.delete: deletion support detection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed bug in CheckSyncToken._run_check():
- Changed cal.save_event(Event, ...) to cal.save_object(Event, ...)
- save_event() doesn't take Event class as first parameter

Added test suite (tests/test_sync_token_check.py):
- Tests correct use of save_object API (would have caught the bug)
- Tests early exit when sync tokens unsupported
- Tests exception handling
- Tests time-based token detection
- Tests fragile token detection

Added conftest.py to ensure tests use local caldav-synctokens library
instead of system-wide installation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Improvements to CheckSyncToken._run_check():
- Pre-cleanup: Delete any leftover csc_sync_test_event_1 from previous failed runs
- Post-cleanup: Use try/finally to ensure event is deleted even if test fails
- Mark test_event as None after successful deletion to avoid double-delete

This ensures the calendar doesn't accumulate test events from failed runs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Implements CheckAlarmSearch to test RFC4791 section 9.9 alarm searches.
Tests if servers support searching for events based on when their alarms
trigger, not when the events themselves occur.

New feature: search.time-range.alarm
- Tests alarm search by creating event at 08:00 with alarm at 07:45
- Verifies search for alarms 08:01-08:07 returns nothing
- Verifies search for alarms 07:40-07:55 finds the event
- Includes pre/post cleanup of test events

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- New CheckPrincipalSearch check class tests:
  - principal-search: Basic principal access
  - principal-search.by-name.self: Search for own principal by name
  - principal-search.list-all: List all principals

Note: principal-search.by-name (general name search) is not tested
as it requires setting up another user with a known name.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- New CheckDuplicateUID check class tests:
  - duplicate-uid.cross-calendar: Can events with same UID exist in different calendars?
  - Support levels: full (allowed), ungraceful (error thrown), unsupported (silently ignored)
  - Verifies events are treated as separate entities when allowed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Prefix feature name with 'save' to follow naming convention for save-related features.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Some CalDAV servers incorrectly return events/todos that fall outside
the requested time range when performing time-range searches. This
particularly affects recurring events where servers may return:
- Recurrences that start after the search interval ends
- Events with no recurrences in the requested time range at all

This commit adds a new compatibility feature "search.time-range.accurate"
to detect this behavior and adjusts assertions accordingly to prevent
the check from failing when encountering buggy servers.

Changes:
- Add "search.time-range.accurate" to CheckRecurrenceSearch features
- Detect time-range accuracy by checking if search returns only expected events
- Make assertions conditional on time-range accuracy support
- Change strict assertions (== 1) to tolerant ones (>= 1) for servers with bugs
- Add detailed comments explaining the expected vs buggy behavior

This allows the compatibility checker to complete successfully even on
servers with time-range bugs, properly documenting the limitation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add CheckFreeBusyQuery class to test RFC4791 free/busy-query REPORT support
- Feature name includes RFC number to distinguish from RFC6638 scheduling freebusy
- Detect servers that don't support freebusy queries (common: 500/501 errors)
- Handle ungraceful responses and unexpected errors appropriately

Bug fixes:
- Initialize principal early in checker to fix standalone script execution
- Handle missing server_name gracefully with fallback to "(noname)"
- Treat 'unknown' support level same as 'fragile' in feature comparisons
- Replace pdb.set_trace() with breakpoint() for modern Python debugging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Instead of creating a new test event (csc_duplicate_uid_test), the check now
reuses csc_simple_event1 which is already created by PrepareCalendar. This
reduces redundant event creation and simplifies the test logic.

Changes:
- Changed test_uid from "csc_duplicate_uid_test" to "csc_simple_event1"
- Replaced event creation with event1 = cal1.event_by_uid(test_uid)
- Updated summary checking logic to compare original vs current instead of
  hardcoded strings
- Removed cleanup that deleted the test event (no longer needed since we
  don't own the event)

Benefits:
- Less code
- Faster execution (no event creation overhead)
- More maintainable (reuses existing test data)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Some general improveements:

 * Script now accepts --caldav-feature to specify what feature-set we should assume.
 * The 'search.cache' server peculiarity is respected, but not checked for

In addition the 'search.comp-type' feature - which I expect to work on all servers except Bedework - is checked, but the check is currently very Bedework-specific.
- Add "search.text.by-uid" to CheckSearch.features_to_be_checked
- Add test that attempts to retrieve event by UID using event_by_uid()
- Test marks feature as:
  - "full" if UID search works correctly
  - "broken" if event is retrieved but UID doesn't match
  - "unsupported" if NotFoundError is raised
  - "ungraceful" if DAVError is raised

This enables automatic discovery of whether servers support searching
for calendar objects by their UID property.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add CheckTimezone class to test server support for non-UTC timezones
- Test creates event with America/Los_Angeles timezone using zoneinfo
- Detects if server rejects events with timezone (403 Forbidden)
- Fix syntax error: mismatched quotes in set_feature call (line 623)
- Add zoneinfo import with Python < 3.9 compatibility fallback

Related to GitHub issue python-caldav/caldav#372 where servers reject events with
timezone information.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
When saving an event with the same UID to a different calendar,
Zimbra moves the event from the original calendar instead of
creating a duplicate (or rejecting it).

This breaks subsequent tests that expect the event to still be
in the original calendar.

Changes:
- Check if event still exists in cal1 after saving to cal2
- Detect "moved-instead-of-copied" behavior
- Move event back to cal1 to restore test state
- Document new behavior in feature description

This ensures tests don't break when running against Zimbra.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Updated CheckSyncToken to use the new disable_fallback parameter in
cal.objects() and cal.objects_by_sync_token() instead of sending
sync-collection REPORT queries directly. This is much cleaner and
more maintainable than bypassing the caldav library.

The disable_fallback parameter prevents the caldav library from
transparently falling back to generating fake sync tokens, allowing
the test to accurately detect whether the server truly supports
sync-collection REPORT.

Changes:
- Use cal.objects(disable_fallback=True) for initial sync token check
- Use cal.objects_by_sync_token(disable_fallback=True) for all subsequent checks
- Removed helper function do_sync_report() - no longer needed
- Removed direct import of dav elements - no longer needed
- Much simpler and cleaner code

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The alarm search test was failing on nextcloud with UNIQUE constraint
violation because it tried to create an event with a UID that already
existed from a previous test run.

Changed the test to:
- Try to find existing event first
- Only create if not found
- Handle duplicate UID gracefully by searching again
- Keep event between runs (removed cleanup/deletion)

This follows the design principle of keeping test events in the calendar
between runs for efficiency, rather than creating and deleting them
each time.

Fixes: UNIQUE constraint violation on nextcloud
Changes:
- Convert search results to list to ensure generator is evaluated
- Call .load() on events to ensure component is loaded
- Use .icalendar_component instead of .component
- Explicitly check for UNIQUE constraint or duplicate errors
- Search again after catching duplicate UID error

This should properly find and reuse existing events instead of
failing with UNIQUE constraint violations.
WORKAROUND: caldav search with parameters (UID, date range) returns 0 results
due to a bug in the async refactoring. Using broad search and manual filtering.

The nextcloud compatibility test revealed this issue:
- Broad search (event=True) works and returns results
- UID search (uid="xxx") returns 0 results
- Date range search (start/end) returns 0 results

This causes the alarm test to fail with UNIQUE constraint because:
1. Event exists in database from previous run
2. Search can't find it (broken parameters)
3. Tries to create duplicate -> UNIQUE constraint violation

The workaround uses broad search and manually filters by UID in memory.

TODO: Fix search parameter handling in async caldav refactoring
Replace workaround code that used broad search with manual filtering
with proper parameterized UID search. The async refactoring works
correctly - search with parameters is not broken.

Changes:
- Use cal.search(uid=..., event=True) instead of broad search + filtering
- Remove debug print statements
- Simplify duplicate UID error handling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Refactored CheckAlarmSearch to follow the same pattern as other checks
by moving the alarm test event creation to PrepareCalendar.

Changes:
- Added alarm test event creation in PrepareCalendar using add_if_not_existing
- Simplified CheckAlarmSearch to use the event created by PrepareCalendar
- Removed redundant event creation and search logic from CheckAlarmSearch
- Restored UID from "csc_alarm_test_event234" to "csc_alarm_test_event"

This improves consistency across the codebase and ensures the alarm test
event is created once and reused, following the established pattern for
test data preparation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants