Functional doctest for calendaring
==================================

This test verifies the security checking for booked resources and
events that book them.

Set up
------

    >>> manager = Browser()
    >>> manager.addHeader('Authorization', 'Basic manager:schooltool')
    >>> manager.handleErrors = False
    >>> manager.open('http://localhost/')

Let's create a person so that we can fool around with his calendar:

    >>> from schooltool.basicperson.browser.ftests.setup import addPerson
    >>> addPerson('Frog', 'Prince', 'frog', 'pwd')

Now let's create some resources that can be booked:

    >>> manager.getLink('Manage').click()
    >>> manager.getLink('Resources').click()

    >>> manager.getLink('Add Resource').click()
    >>> manager.getControl('Title').value = 'lilly'
    >>> manager.getControl('Add').click()

After adding a lilly we should see the Resource in the resource type
filter box available:

    >>> "<h3>Resource</h3>" in manager.contents
    True

Let's click on it:

    >>> manager.getLink('Resource', index=2).click()
    >>> 'lilly' in manager.contents
    True

    >>> manager.getLink('Add Resource').click()
    >>> manager.getControl('Title').value = 'mud'
    >>> manager.getControl('Add').click()
    >>> manager.getLink('Resource', index=2).click()
    >>> 'mud' in manager.contents
    True

    >>> manager.getLink('Add Resource').click()
    >>> manager.getControl('Title').value = 'fish'
    >>> manager.getControl('Add').click()
    >>> manager.getLink('Resource', index=2).click()
    >>> 'fish' in manager.contents
    True

We log in as the frog

    >>> frog = Browser('frog', 'pwd')

and set up a calendar for Frog:

    >>> print http(r"""
    ... PUT /persons/frog/calendar/calendar.ics HTTP/1.1
    ... Host: localhost:7080
    ... Authorization: Basic frog:pwd
    ... Content-Length: 244
    ... Content-Type: text/calendar
    ...
    ... BEGIN:VCALENDAR
    ... VERSION:2.0
    ... PRODID:-//SchoolTool.org/NONSGML SchoolTool//EN
    ... BEGIN:VEVENT
    ... UID:dummy-uid
    ... SUMMARY:Test event
    ... DTSTART:20050204T100000
    ... DURATION:PT1H
    ... DTSTAMP:20050203T150000
    ... END:VEVENT
    ... END:VCALENDAR
    ... """, handle_errors=False)
    HTTP/1.1 200 Ok
    Cache-Control: no-cache="Set-Cookie,Set-Cookie2"
    Content-Length: 0
    Expires: ...
    Pragma: no-cache
    Set-Cookie: ...
    <BLANKLINE>

Frog should not be capable of booking any resources yet:

    >>> frog.open('http://localhost/persons/frog/calendar/2005-02-04')
    >>> frog.getLink('Test event').click()

    >>> import traceback
    >>> from zope.exceptions.exceptionformatter import print_exception
    >>> traceback.print_exception = print_exception

    >>> frog.handleErrors = False
    >>> frog.getLink('Book resources').click()
    >>> print frog.contents
    <BLANKLINE>
    ...
    <legend>Available Resources</legend>
    ...

But we can give him that right by making him a leader of that
resource:

    >>> manager.open('http://localhost/resources/mud/@@leaders.html')
    >>> manager.getControl('Frog').click()
    >>> manager.getControl('Add').click()

    >>> manager.open('http://localhost/resources/fish/@@leaders.html')
    >>> manager.getControl('Frog').click()
    >>> manager.getControl('Add').click()

Frog should see the mud and the fish now:

    >>> frog.open(frog.url)
    >>> print frog.contents
    <BLANKLINE>
    ...
      <fieldset>
          <legend>Available Resources</legend>
    ...
          <input type="checkbox" name="add_item.fish" id="add_item.fish" />
    ...
          <input type="checkbox" name="add_item.mud" id="add_item.mud" />
    ...
        </table>
    ...
      </fieldset>
    ...

Let's book one of them:

    >>> frog.getControl('mud').selected = True
    >>> frog.getControl('Book').click()

We should see the resource as a booked resource:

    >>> frog.open('http://localhost/persons/frog/calendar/2005-02-04')
    >>> frog.getLink('Test event').click()
    >>> frog.getLink('Book resources').click()
    >>> print frog.contents
    <BLANKLINE>
    ...
        <input type="checkbox" name="remove_item.mud" id="remove_item.mud" />
    ...

     <fieldset>
          <legend>Available Resources</legend>
    ...
          <input type="checkbox" name="add_item.fish" id="add_item.fish"/>
    ...
      </fieldset>
    ...

Let's unbook one of them and book another:

    >>> frog.getControl('mud').selected = True
    >>> frog.getControl('UnBook').click()
    >>> frog.getControl('fish').selected = True
    >>> frog.getControl('Book').click()

Now another resource is booked

Frog should see the event in the resource calendar too:

    >>> frog.open(
    ...     'http://localhost/resources/fish/calendar/2005-02-04/')
    >>> print frog.contents
    <BLANKLINE>
    ...
    <a href="http://localhost/persons/frog/calendar/ZHVtbXktdWlk/edit.html?date=2005-02-04&amp;back_url=http%3A//localhost/resources/fish/calendar&amp;cancel_url=http%3A//localhost/resources/fish/calendar"
       title="Test event">
      Test event
      <span class="start-end">
        (<span>10:00</span> -
        <span>11:00</span>)
      </span>
    </a>
    ...
    <div class="booked-resources">
      <h6 class="booked-resource-header"
               style="background: #7590ae">
        <a style="color: #000;"
           href="...ZHVtbXktdWlk/booking.html?date=2005-02-04">Booked by</a></h6>
      <a href="http://localhost/persons/frog">Frog Prince</a>
    </div>
    ...

If Frog decides to book another resource from the resource's calendar,
and then changes his mind by clicking on Cancel, the resource won't be
booked.

    >>> frog.open('http://localhost/resources/fish/calendar')
    >>> frog.getLink('10:00').click()
    >>> frog.getControl('Title').value="Canceled Event"
    >>> frog.getControl('Cancel').click()
    >>> 'Canceled Event' not in frog.contents
    True

Now if we remove the permission to book the fish:

    >>> manager.open('http://localhost/resources/fish/@@leaders.html')
    >>> manager.getControl('Frog').click()
    >>> manager.getControl('Remove').click()

The fish should stay in the bookable resources list:

    >>> frog.open('http://localhost/persons/frog/calendar/2005-02-04')
    >>> frog.getLink('Test event').click()
    >>> frog.getLink('Book resources').click()
    >>> print frog.contents
    <BLANKLINE>
    ...
      <fieldset>
        <legend>Booked Resources</legend>
    ...
        <input type="checkbox" name="remove_item.fish" id="remove_item.fish" />
    ...
      </fieldset>
    ...

Unless unbooked:

    >>> frog.getControl('fish').selected = True
    >>> frog.getControl('UnBook').click()
    >>> 'name="add_item.fish" id="add_item.fish"' not in frog.contents
    True


When adding a new event we should get redirected to resource booking
if Book Resources is checked:

    >>> frog.getLink('Calendar').click()
    >>> frog.getLink('New Event').click()
    >>> frog.getControl('Title').value = 'Sleeping'
    >>> frog.getControl('Date').value = '2005-02-03'
    >>> frog.getControl('Time').value = '01:00'
    >>> frog.getControl('Duration').value = '500'
    >>> frog.getControl('Recurring').selected = True
    >>> frog.getControl(name='field.recurrence.used').value = '1'
    >>> frog.getControl('Book Resources').selected = True
    >>> frog.getControl('Add').click()

    >>> 'Resource Booking for Sleeping' in frog.contents
    True

Editing view should have a link to its booking view:

    >>> frog.open(
    ...   'http://localhost/persons/frog/calendar/ZHVtbXktdWlk/edit.html')
    >>> frog.getLink('Book resources')
    <Link text='Book resources'
          url='.../frog/calendar/ZHVtbXktdWlk/booking.html'>

Let's book the mud again (Regression test for 266, deletion of events that book
resources should remove events from resource calendars):

    >>> frog.getLink('Book resources').click()
    >>> frog.getControl('mud').selected = True
    >>> frog.getControl('Book').click()

We can see the event in mud's calendar:

    >>> frog.open('http://localhost/resources/mud/calendar/2005-02-04')
    >>> print frog.contents
    <BLANKLINE>
    ...
    <a style="color: #000;"
       href="http://.../booking.html?date=2005-02-04">Booked by</a></h6>
    ...

If we will delete the event from mud's calendar the original event
should stay in place, yet the resource should become unbooked:

    XXX: Have to call URL, since I could not find the link!!!
    >>> manager.open('http://localhost/resources/mud/calendar/'
    ...           'delete.html?event_id=dummy-uid&date=2005-02-04')
    >>> manager.getControl('Delete').click()
    >>> 'Test event' in manager.contents
    False

Frog still can see the event:

    >>> frog.open('http://localhost/persons/frog/calendar/2005-02-04')
    >>> 'Test event' in frog.contents
    True

Yet mud is not booked anymore:

    >>> frog.getLink('Test event').click()
    >>> frog.getLink('Book resources').click()
    >>> print frog.contents
    <BLANKLINE>
    ...
          <input type="checkbox" name="add_item.mud" id="add_item.mud" />
    ...

Let's book it again:

    >>> frog.getControl('mud').selected = True
    >>> frog.getControl('Book').click()

It is in mud's calendar again:

    >>> frog.open('http://localhost/resources/mud/calendar/2005-02-04')
    >>> print frog.contents
    <BLANKLINE>
    ...
    <a style="color: #000;"
       href="http://.../booking.html?date=2005-02-04">Booked by</a></h6>
    ...

And delete the event from frog's calendar:

    >>> manager.open(
    ...     'http://localhost/persons/frog/calendar/2005-02-04')
    >>> manager.getLink(url='delete.html?event_id=dummy-uid').click()
    >>> manager.getControl('Delete').click()

The event should be gone from the frog's calendar:

    >>> frog.open('http://localhost/persons/frog/calendar/2005-02-04')
    >>> "dummy-uid" in frog.contents
    False

And it should not be seen in mud's calendar too:

    >>> frog.open('http://localhost/resources/mud/calendar/2005-02-04')
    >>> "dummy-uid" in frog.contents
    False

Let's do some event clashing, first we set up some overlapping events:

    >>> print http(r"""
    ... PUT /persons/frog/calendar/calendar.ics HTTP/1.1
    ... Host: localhost:7080
    ... Authorization: Basic frog:pwd
    ... Content-Length: 244
    ... Content-Type: text/calendar
    ...
    ... BEGIN:VCALENDAR
    ... VERSION:2.0
    ... PRODID:-//SchoolTool.org/NONSGML SchoolTool//EN
    ... BEGIN:VEVENT
    ... UID:dummy-uid1
    ... SUMMARY:Test event1
    ... DTSTART:20050204T093000
    ... DURATION:PT1H
    ... DTSTAMP:20050203T150000
    ... END:VEVENT
    ... BEGIN:VEVENT
    ... UID:dummy-uid2
    ... SUMMARY:Test event2
    ... DTSTART:20050204T100000
    ... DURATION:PT1H
    ... DTSTAMP:20050203T150000
    ... END:VEVENT
    ... BEGIN:VEVENT
    ... UID:dummy-uid3
    ... SUMMARY:Test event3
    ... DTSTART:20050204T103000
    ... DURATION:PT1H
    ... DTSTAMP:20050203T150000
    ... END:VEVENT
    ... END:VCALENDAR
    ... """, handle_errors=False)
    HTTP/1.1 200 Ok
    Content-Length: 0
    <BLANKLINE>

Now let's allow frog access all resources:

    >>> manager.open('http://localhost')

    >>> manager.getLink('Manage').click()
    >>> manager.getLink('Resources').click()
    >>> manager.getLink('Resource', index=2).click()
    >>> manager.getLink('mud').click()
    >>> manager.getLink('View Calendar').click()

    >>> manager.open('http://localhost/resources/fish/@@leaders.html')
    >>> manager.getControl('Frog').click()
    >>> manager.getControl('Add').click()

If we book some resources for the second event,

    >>> frog.handleErrors = False
    >>> frog.open(
    ...     'http://localhost/persons/frog/calendar/ZHVtbXktdWlkMg%3D%3D')
    >>> frog.getLink('edit resources').click()
    >>> frog.getControl('mud').selected = True
    >>> frog.getControl('fish').selected = True
    >>> frog.getControl('Book').click()

Unless we are looking at "Test event2" itself:

    >>> frog.open('http://localhost/persons/frog/calendar/ZHVtbXktdWlkMg%3D%3D')
    >>> frog.getLink('edit resources').click()
    >>> 'type="checkbox" name="remove_item.fish"' in frog.contents
    True
    >>> 'type="checkbox" name="remove_item.mud"' in frog.contents
    True

Let's add another person, frog's boss:

    >>> addPerson('Stork', 'Hunter', 'stork', 'pwd')

The boss decides to take a mud bath, so he creates an event.

    >>> print http(r"""
    ... PUT /persons/stork/calendar/calendar.ics HTTP/1.1
    ... Host: localhost:7080
    ... Authorization: Basic stork:pwd
    ... Content-Type: text/calendar
    ...
    ... BEGIN:VCALENDAR
    ... VERSION:2.0
    ... PRODID:-//SchoolTool.org/NONSGML SchoolTool//EN
    ... BEGIN:VEVENT
    ... UID:smartie-uid
    ... SUMMARY:Mud bath
    ... DTSTART:20050807T100000
    ... DURATION:PT2H
    ... DTSTAMP:20050818T150000
    ... END:VEVENT
    ... END:VCALENDAR
    ... """, handle_errors=False)
    HTTP/1.1 200 Ok
    Content-Length: 0
    <BLANKLINE>

Stork should have access to the resources:

    >>> manager.open('http://localhost/resources/mud/@@leaders.html')
    >>> manager.getControl('Stork').click()
    >>> manager.getControl('Add').click()

And then stork books mud.

    >>> stork = Browser()
    >>> stork.open('http://localhost/')
    >>> stork.getLink('Log In').click()
    >>> stork.getControl('Username').value = 'stork'
    >>> stork.getControl('Password').value = 'pwd'
    >>> stork.getControl('Log in').click()

    >>> stork.open(
    ...     'http://localhost/persons/stork/calendar/c21hcnRpZS11aWQ%3D')
    >>> stork.getLink('edit resources').click()
    >>> stork.getControl('mud').selected = True
    >>> stork.getControl('Book').click()

Frog should still be able to see the resource's calendar
(regression test for issue 352):

    >>> frog.open('http://localhost/resources/mud/calendar/2005-08-07')
    >>> print frog.contents
    <BLANKLINE>
    ...
    <h6 ...>
      <a href="http://localhost/resources/mud/calendar/c21hcnRpZS11aWQ%3D"
         title="Mud bath">
        Mud bath
      ...
    </h6>
    ...

Let's delete mud:

    >>> manager.open('http://localhost/resources/')
    >>> manager.getLink('Resource', index=2).click()
    >>> manager.getControl(name='delete.mud').value = True
    >>> manager.getControl('Delete').click()
    >>> manager.getControl('Confirm').click()

Stork should still be able to see his calendar:
(regression test for issue 472: Deleting booked resource makes calendar
 unviewable.)

    >>> stork.open('http://localhost/persons/stork/calendar/2005-08-07')
    >>> print stork.contents
    <BLANKLINE>
    ...
    <h6 ...>
      <a href="http://localhost/persons/stork/calendar/c21hcnRpZS11aWQ%3D/edit.html?date=2005-08-07&amp;back_url=http%3A//localhost/persons/stork/calendar&amp;cancel_url=http%3A//localhost/persons/stork/calendar"
         title="Mud bath">
        Mud bath
      ...
    </h6>
    ...

Now, let's test the paging, for that we'll need to create a profuse amount of resources.

    >>> manager.open('http://localhost/resources')
    >>> manager.getLink('Import Resources').click()
    >>> moofest = """mooa
    ... moob
    ... mooc
    ... mood
    ... mooe
    ... moof
    ... moog
    ... mooh
    ... mooi
    ... mooj
    ... mook
    ... mool
    ... moom
    ... moon
    ... mooo
    ... moop
    ... mooq
    ... moor
    ... moos
    ... moot
    ... moou
    ... moov
    ... moow
    ... moox
    ... mooy
    ... mooz
    ... """
    >>> manager.getControl('CSV Data').value = moofest
    >>> manager.getControl('Submit').click()

Now let's create an event for the manager.

    >>> manager.getLink('Calendar').click()
    >>> manager.getLink('New Event').click()
    >>> manager.getControl('Title').value = 'Moo Fest'
    >>> manager.getControl('Date').value = '2005-02-03'
    >>> manager.getControl('Time').value = '01:00'
    >>> manager.getControl('Duration').value = '500'
    >>> manager.getControl('Recurring').selected = True
    >>> manager.getControl(name='field.recurrence.used').value = '1'
    >>> manager.getControl('Book Resources').selected = True
    >>> manager.getControl('Add').click()

Now on to play with the paging! The default batch size is 25, keeping in mind the 2 reources created before
the 11 item should be `moox`.

    >>> manager.getLink('2').click()
    >>> print manager.contents
    <BLANKLINE>
    ...
    <input type="checkbox" name="add_item.moox" id="add_item.moox" />
    ...

Howevever, `mooa` should not be in the list.

    >>> '<input type="checkbox" name="add_item.mooa" id="add_item.mooa" />' not in manager.contents
    True

Let's test the searching, we have a bunch of moos, so let's search for `moo`.
Now `mooj` should be the tenth in the item and `mooa` should be the first.

    >>> manager.getControl(name="SEARCH_TITLE").value = "moo"
    >>> manager.getControl(name="SEARCH_BUTTON").click()
    >>> print manager.contents
    <BLANKLINE>
    ...
    <input type="checkbox" name="add_item.mooa" id="add_item.mooa" />
    ...
    <input type="checkbox" name="add_item.mooj" id="add_item.mooj" />
    ...

The item `mud` should not be in the list.

    >>> '<input type="checkbox" name="add_item.mud" id="add_item.mud" />' not in manager.contents
    True

Let's search for something specific.

    >>> manager.getControl(name="SEARCH_TITLE").value = "fish"
    >>> manager.getControl(name="SEARCH_BUTTON").click()
    >>> print manager.contents
    <BLANKLINE>
    ...
    <input type="checkbox" name="add_item.fish" id="add_item.fish" />
    ...

We shouldn't have any extra items after the search query:

    >>> '<input type="checkbox" name="add_item.mud" id="add_item.mud" />' not in manager.contents
    True

Let's check the booked resources in the weekly view of the calendar
for frog:

    >>> frog.open('http://localhost:8000/persons/frog/calendar/2005-w05')
    >>> frog.printQuery('id("calendar-view-week")/tr[3]/td[5]/div/div/a')
    <a href="..."
       title="Test event2">
      <span>Test event2</span>
      (<span>10:00</span> - <span>11:00</span>)
    </a>
    >>> frog.printQuery('id("calendar-view-week")/tr[3]/td[5]//'
    ...                 'div[@class="booked-resources"]//a/text()')
    Booked resources
    fish
    Booked by
    Frog Prince
