# HG changeset patch # User Paul Boddie # Date 1443827128 -7200 # Node ID a71df796169c7463a9f9d497134a8329b7627699 # Parent 7de8236d3faea11d1a09c40769011a3d8cf8e077 Added a test of counter-proposals with the outgoing handler. Added counter-proposal support to the test handler/client script. diff -r 7de8236d3fae -r a71df796169c tests/test_handle.py --- a/tests/test_handle.py Sat Oct 03 01:04:41 2015 +0200 +++ b/tests/test_handle.py Sat Oct 03 01:05:28 2015 +0200 @@ -21,7 +21,9 @@ from imiptools.client import ClientForObject from imiptools.data import Object, get_address, parse_object +from imiptools.dates import get_datetime, to_timezone from imiptools.mail import Messenger +from imiptools.period import RecurringPeriod import imip_store import sys @@ -34,16 +36,38 @@ # Action methods. - def handle_request(self, accept): + def handle_request(self, action, start=None, end=None): """ - Process the current request for the current user. Return whether any - action was taken. + Process the current request for the current user. Return whether the + given 'action' was taken. + + If 'start' and 'end' are specified, they will be used in any + counter-proposal. """ # Reply only on behalf of this user. - attendee_attr = self.update_participation(self.obj, accept and "ACCEPTED" or "DECLINED") + if action in ("accept", "decline"): + attendee_attr = self.update_participation(self.obj, action == "accept" and "ACCEPTED" or "DECLINED") + method = "REPLY" + + # For counter-proposals, set a new main period for the event. + + elif action == "counter": + attendee_attr = self.obj.get_value_map("ATTENDEE").get(self.user) + period = self.obj.get_main_period(self.get_tzid()) + + # Use the existing or configured time zone for the specified + # datetimes. + + start = to_timezone(get_datetime(start), period.tzid) + end = to_timezone(get_datetime(end), period.tzid) + period = RecurringPeriod(start, end, period.tzid, period.origin, period.get_start_attr(), period.get_end_attr()) + self.obj.set_period(period) + method = "COUNTER" + else: + return None if not attendee_attr: return None @@ -57,7 +81,7 @@ self.set_sequence(False) message = self.messenger.make_outgoing_message( - [self.obj.to_part("REPLY")], + [self.obj.to_part(method)], [organiser], outgoing_bcc=get_address(self.user) ) @@ -69,14 +93,30 @@ if __name__ == "__main__": try: - minargs = 3; maxargs = 5 - accept, store_dir, user, uid, recurrenceid = (sys.argv[1:maxargs+1] + ([None] * (maxargs - minargs)))[:maxargs] + action, store_dir, user = sys.argv[1:4] + if action == "counter": + start, end = sys.argv[4:6] + i = 6 + else: + start, end = None, None + i = 4 + uid, recurrenceid = (sys.argv[i:i+2] + [None] * 2)[:2] except ValueError: - print >>sys.stderr, "Need 'accept' or 'decline', a store directory, user URI, event UID and optional RECURRENCE-ID." - print >>sys.stderr, "The RECURRENCE-ID must be in the form employed by the store." - print >>sys.stderr - print >>sys.stderr, "Alternatively, omit the UID and RECURRENCE-ID and provide event-only details on standard input" - print >>sys.stderr, "to force the script to handle an event not already present in the store." + print >>sys.stderr, """\ +Need 'accept', 'counter' or 'decline', a store directory, user URI, any +counter-proposal datetimes (see below), plus the appropriate event UID and +RECURRENCE-ID (if a recurrence is involved). + +The RECURRENCE-ID must be in exactly the form employed by the store, not a +different but equivalent representation. + +Alternatively, omit the UID and RECURRENCE-ID and provide event-only details on +standard input to force the script to handle an event not already present in the +store. + +If 'counter' has been indicated, alternative start and end datetimes are also +required. +""" sys.exit(1) store = imip_store.FileStore(store_dir) @@ -92,7 +132,7 @@ obj = Object(fragment) handler = TestClient(obj, user, Messenger(), store) - response = handler.handle_request(accept == "accept") + response = handler.handle_request(action, start, end) if response: if uid is not None: diff -r 7de8236d3fae -r a71df796169c tests/test_person_invitation_counter.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test_person_invitation_counter.sh Sat Oct 03 01:05:28 2015 +0200 @@ -0,0 +1,122 @@ +#!/bin/sh + +THIS_DIR=`dirname $0` + +TEMPLATES="$THIS_DIR/templates" +PERSON_SCRIPT="$THIS_DIR/../imip_person.py" +SHOWMAIL="$THIS_DIR/../tools/showmail.py" +STORE=/tmp/store +STATIC=/tmp/static +PREFS=/tmp/prefs +ARGS="-S $STORE -P $STATIC -p $PREFS -d" +USER="mailto:vincent.vole@example.com" +SENDER="mailto:paul.boddie@example.com" +FBFILE="$STORE/$USER/freebusy" +FBOFFERFILE="$STORE/$USER/freebusy-offers" +FBSENDERFILE="$STORE/$SENDER/freebusy" +FBSENDEROTHERFILE="$STORE/$SENDER/freebusy-other/$USER" +FBSENDERREQUESTS="$STORE/$SENDER/requests" +TAB=`printf '\t'` + +OUTGOING_SCRIPT="$THIS_DIR/../imip_person_outgoing.py" + +PYTHONPATH="$THIS_DIR/.." +export PYTHONPATH + +ACCEPT_SCRIPT="$THIS_DIR/test_handle.py" +ACCEPT_ARGS="accept $STORE" + +COUNTER_SCRIPT="$THIS_DIR/test_handle.py" +COUNTER_ARGS="counter $STORE" + +DECLINE_SCRIPT="$THIS_DIR/test_handle.py" +DECLINE_ARGS="decline $STORE" + +ERROR=err.tmp + +rm -r $STORE +rm -r $STATIC +rm -r $PREFS +rm $ERROR +rm out*.tmp + +mkdir -p "$PREFS/$USER" +echo 'Europe/Oslo' > "$PREFS/$USER/TZID" +echo 'share' > "$PREFS/$USER/freebusy_sharing" +echo 'PT60S' > "$PREFS/$USER/freebusy_offers" + + "$PERSON_SCRIPT" $ARGS < "$TEMPLATES/fb-request-person-all.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out0.tmp + + grep -q 'METHOD:REPLY' out0.tmp \ +&& ! grep -q '^FREEBUSY' out0.tmp \ +&& echo "Success" \ +|| echo "Failed" + +# Attempt to schedule an event. + +"$OUTGOING_SCRIPT" $ARGS < "$TEMPLATES/event-request-person.txt" 2>> $ERROR + + grep -q "^20141126T150000Z${TAB}20141126T160000Z" "$FBSENDERFILE" \ +&& echo "Success" \ +|| echo "Failed" + +# Present the request to the recipient. + + "$PERSON_SCRIPT" $ARGS < "$TEMPLATES/event-request-person.txt" 2>> $ERROR \ +| "$SHOWMAIL" \ +> out1.tmp + + ! grep -q 'METHOD:REPLY' out1.tmp \ +&& echo "Success" \ +|| echo "Failed" + + ! [ -e "$FBFILE" ] \ +|| ! grep -q "event6@example.com" "$FBFILE" \ +&& echo "Success" \ +|| echo "Failed" + + ! [ -e "$FBOTHERFILE" ] \ +|| ! grep -q "event6@example.com" "$FBOTHERFILE" \ +&& echo "Success" \ +|| echo "Failed" + +# Counter the invitation. + + "$COUNTER_SCRIPT" $COUNTER_ARGS "$USER" 20141126T170000 20141126T180000 "event6@example.com" 2>> $ERROR \ +| tee out2r.tmp \ +| "$SHOWMAIL" \ +> out2.tmp + +# Note that the invitation has only been prepared, not processed. + + ! [ -e "$FBFILE" ] \ +|| ( ! grep -q "^20141126T150000Z${TAB}20141126T160000Z" "$FBFILE" \ + && ! grep -q "^20141126T160000Z${TAB}20141126T170000Z" "$FBFILE" ) \ +&& echo "Success" \ +|| echo "Failed" + + grep -q 'METHOD:COUNTER' out2.tmp \ +&& grep -q 'DTSTART;TZID=Europe/Oslo.*:20141126T170000' out2.tmp \ +&& echo "Success" \ +|| echo "Failed" + + ! [ -e "$FBOFFERFILE" ] \ +|| ! grep -q "^20141126T160000Z${TAB}20141126T170000Z" "$FBOFFERFILE" \ +&& echo "Success" \ +|| echo "Failed" + +# Send the counter-proposal. + +"$OUTGOING_SCRIPT" $ARGS < out2r.tmp 2>> $ERROR + + ! [ -e "$FBFILE" ] \ +|| ( ! grep -q "^20141126T150000Z${TAB}20141126T160000Z" "$FBFILE" \ + && ! grep -q "^20141126T160000Z${TAB}20141126T170000Z" "$FBFILE" ) \ +&& echo "Success" \ +|| echo "Failed" + + grep -q "^20141126T160000Z${TAB}20141126T170000Z" "$FBOFFERFILE" \ +&& echo "Success" \ +|| echo "Failed"