# Testing Calendar

Calendar mocks - getting, creating, updating, deleting and responding to events.

Mock Calendar connections to test services that work with events, calendars, and scheduling.

**Note:** If you're new to unit testing with Zato, check the [tutorial](https://zato.io/docs/api-testing/tutorial.html) first.

## Getting events {#getting-events}

**The service**:

```python
from zato.server.service import Service

class GetCalendarEvents(Service):
    name = 'calendar.events.get'

    def handle(self):
        conn = self.microsoft.cloud['ms365.Calendar']

        schedule = conn.schedule()
        calendar = schedule.get_default_calendar()
        events = calendar.get_events()

        self.response.payload = {
            'events': [{'subject': e['subject'], 'start': e['start']} for e in events]
        }
```

**The test**:

```python
from zato_testing import ServiceTestCase
from myapp.services import GetCalendarEvents

class TestGetCalendarEvents(ServiceTestCase):

    def test_returns_events(self):

        self.set_response('ms365.Calendar.schedule', {'id': 'schedule-123'})
        self.set_response('ms365.Calendar.schedule.get_default_calendar', {'id': 'cal-456'})
        self.set_response('ms365.Calendar.schedule.get_default_calendar.get_events', [
            {'subject': 'Team Meeting', 'start': '2024-03-20T10:00:00'},
            {'subject': 'Project Review', 'start': '2024-03-20T14:00:00'},
            {'subject': 'Weekly Sync', 'start': '2024-03-21T09:00:00'}
        ])

        service = self.invoke(GetCalendarEvents)

        events = service.response.payload['events']
        self.assertEqual(len(events), 3)
        self.assertEqual(events[0]['subject'], 'Team Meeting')
```

## Creating events {#creating-events}

**The service**:

```python
class CreateCalendarEvent(Service):
    name = 'calendar.event.create'
    input = 'subject', 'start', 'end', '-attendees'

    def handle(self):
        conn = self.microsoft.cloud['ms365.Calendar']

        schedule = conn.schedule()
        calendar = schedule.get_default_calendar()
        event = calendar.new_event()
        event.subject = self.request.input.subject
        event.start = self.request.input.start
        event.end = self.request.input.end

        for attendee in self.request.input.attendees or []:
            event.add_attendee(attendee)

        result = event.save()

        self.response.payload = {'created': result, 'event_id': event.object_id}
```

**The test**:

```python
class TestCreateCalendarEvent(ServiceTestCase):

    def test_creates_event(self):

        self.set_response('ms365.Calendar.schedule', {'id': 'schedule-123'})
        self.set_response('ms365.Calendar.schedule.get_default_calendar', {'id': 'cal-456'})
        self.set_response('ms365.Calendar.schedule.get_default_calendar.new_event', {
            'object_id': 'event-new-001',
            'subject': None,
            'start': None,
            'end': None
        })
        self.set_response('ms365.Calendar.schedule.get_default_calendar.new_event.add_attendee', None)
        self.set_response('ms365.Calendar.schedule.get_default_calendar.new_event.save', True)

        service = self.invoke(CreateCalendarEvent,
            subject='New Meeting',
            start='2024-03-25T10:00:00',
            end='2024-03-25T11:00:00',
            attendees=['colleague@example.com']
        )

        self.assertEqual(service.response.payload['created'], True)
        self.assertEqual(service.response.payload['event_id'], 'event-new-001')
```

## Listing calendars {#listing-calendars}

```python
class TestGetCalendars(ServiceTestCase):

    def test_returns_calendars(self):

        self.set_response('ms365.Calendar.schedule', {'id': 'schedule-123'})
        self.set_response('ms365.Calendar.schedule.list_calendars', [
            {'name': 'Calendar', 'id': 'cal-001'},
            {'name': 'Work', 'id': 'cal-002'},
            {'name': 'Personal', 'id': 'cal-003'}
        ])

        service = self.invoke(GetCalendars)

        self.assertEqual(len(service.response.payload['calendars']), 3)
```

## Updating events {#updating-events}

```python
class TestUpdateCalendarEvent(ServiceTestCase):

    def test_updates_event(self):

        self.set_response('ms365.Calendar.schedule', {'id': 'schedule-123'})
        self.set_response('ms365.Calendar.schedule.get_default_calendar', {'id': 'cal-456'})
        self.set_response('ms365.Calendar.schedule.get_default_calendar.get_event', {
            'id': 'event-001',
            'subject': 'Old Subject',
            'start': '2024-03-20T10:00:00',
            'end': '2024-03-20T11:00:00'
        })
        self.set_response('ms365.Calendar.schedule.get_default_calendar.get_event.save', True)

        service = self.invoke(UpdateCalendarEvent,
            event_id='event-001',
            updates={'subject': 'Updated Subject'}
        )

        self.assertEqual(service.response.payload['updated'], True)
```

## Deleting events {#deleting-events}

```python
class TestDeleteCalendarEvent(ServiceTestCase):

    def test_deletes_event(self):

        self.set_response('ms365.Calendar.schedule', {'id': 'schedule-123'})
        self.set_response('ms365.Calendar.schedule.get_default_calendar', {'id': 'cal-456'})
        self.set_response('ms365.Calendar.schedule.get_default_calendar.get_event', {
            'id': 'event-001',
            'subject': 'Event to Delete'
        })
        self.set_response('ms365.Calendar.schedule.get_default_calendar.get_event.delete', True)

        service = self.invoke(DeleteCalendarEvent, event_id='event-001')

        self.assertEqual(service.response.payload['deleted'], True)
```

## Responding to events {#responding-to-events}

```python
class TestRespondToEvent(ServiceTestCase):

    def test_accepts_event(self):

        self.set_response('ms365.Calendar.schedule', {'id': 'schedule-123'})
        self.set_response('ms365.Calendar.schedule.get_default_calendar', {'id': 'cal-456'})
        self.set_response('ms365.Calendar.schedule.get_default_calendar.get_event', {
            'id': 'event-001',
            'subject': 'Meeting Invite'
        })
        self.set_response('ms365.Calendar.schedule.get_default_calendar.get_event.accept_event', True)

        service = self.invoke(RespondToEvent, event_id='event-001', response='accept')

        self.assertEqual(service.response.payload['responded'], True)
```

## Learn more {#learn-more}

- [API testing](https://zato.io/docs/api-testing/) - Tests in plain English, run against real or mocked connections
- [API testing tutorial](https://zato.io/docs/api-testing/tutorial.html) - A complete test suite, from the first scenario to the report
- [Testing REST connections](https://zato.io/docs/api-testing/rest.html) - Mock outgoing REST calls and assert on what your service sent
- [Testing SQL connections](https://zato.io/docs/api-testing/sql.html) - Mock database queries and the rows they return
- [Testing LDAP connections](https://zato.io/docs/api-testing/ldap.html) - Mock directory lookups and the entries they find
- [Testing Microsoft 365](https://zato.io/docs/api-testing/ms365/) - Mock mailboxes, calendars, SharePoint, Teams and the rest
- [Testing service invocations](https://zato.io/docs/api-testing/services.html) - Services that call other services, with the callees mocked
- [Testing Jira connections](https://zato.io/docs/api-testing/jira.html) - Mock Jira API calls and the issues they return
- [Tests in CI/CD](https://zato.io/docs/api-testing/ci-cd.html) - Running the suite in a pipeline and reading its output
