Craig Burke

Migrating my email to outlook.com

One of the things I’ve been meaning to do is to migrate my email to a free hosted service so that I don’t have to spend the time managing my own server (or paying for it). My main requirements were that I wanted to retain my custom domain email (craig@craigburke.com) and also get access to a decent webmail client all without paying anything for it. Since Google recently stopped allowing people to sign up for free Google Apps accounts, that rules them out as a free option for most people. If you had signed up for a Google Apps account prior to this change, then you should be grandfathered in and can still go the free email route. I’m in this category, but I honestly find gmail to be a bit clunky. If you still want to use gmail with a custom domain email and haven’t previously signed up, you’ll have to pay $50/year to do so. The other free email option I looked at was outlook.com, which is Microsoft’s revamped version of Hotmail. I’m definitely no fan of Hotmail or anything that Microsoft touches, but man, did they get their webmail client right. It’s simple, clean and incredibly fast. It also has an edge over gmail with seemingly unlimited storage and up to 500 users per domain. Here’s what my inbox looks like right now:

image

Read More

Google Calendar in Grails - Adding Tests with Spock

I went to the GR8 Conference in Minnesota last week and met some cool people and learned about some grails related stuff that got me pretty excited. Inspired by Zan Thrash’s excellent Spock Soup to Nuts presentation, I decided to revisit my Google Calendar grails projects and add some Spock tests. It seems as though more and more people are actually trying to use it in their own projects, so I’d like to give people a better base to work from. Given the fact that the project currently has exactly zero tests I think I could probably do a bit better in the test coverage area. So first I’m going to write some Spock tests to exercise the app (specifically the rather complicated EventService). Now ideally these would have been written first, but better late than never. The tests in Spock tend to be a little easier to read and allow you to create some nice data driven tests. Since a few people pointed out to me that they were getting exceptions with weekly events that didn’t have any excluded days, I’ll use this as an opportunity to try out Spock and write a few tests to see if I can reproduce this. So after installing the spock plugin, here’s what my unit test looks like for EventService:
package com.craigburke

import grails.test.mixin.*
import grails.plugin.spock.*
import spock.lang.*

import org.joda.time.*
import static org.joda.time.DateTimeConstants.*

@TestFor(EventService)
@Mock(Event)
class EventServiceSpec extends UnitSpec {

    @Shared DateTime now
    @Shared DateTime mondayNextWeek
    @Shared DateTime wednesdayNextWeek
    @Shared DateTime fridayNextWeek
    @Shared DateTime mondayAfterNext

    @Shared Event mwfEvent

    def setupSpec() {
        now = new DateTime()
        mondayNextWeek = new DateTime().plusWeeks(1).withDayOfWeek(MONDAY).withTime(0,0,0,0)
        wednesdayNextWeek = mondayNextWeek.withDayOfWeek(WEDNESDAY)
        fridayNextWeek = mondayNextWeek.withDayOfWeek(FRIDAY)
        mondayAfterNext = mondayNextWeek.plusWeeks(1)

        mwfEvent = new Event(
                title: 'Repeating MWF Event',
                startTime: mondayNextWeek.toDate(),
                endTime: mondayNextWeek.plusHours(1).toDate(),
                location: "Regular location",
                recurType: EventRecurType.WEEKLY,
                isRecurring: true,
                recurDaysOfWeek: [MONDAY, WEDNESDAY, FRIDAY]
        )

    }

    @Unroll("next occurance of weekly event after #afterDate")
    def "next occurrence of a weekly event without excluded days"() {
        expect:
            service.findNextOccurrence(event, afterDate.toDate()) == expectedResult.toDate()

        where:
            event    | afterDate         | expectedResult
            mwfEvent | now               | mondayNextWeek
            mwfEvent | mondayNextWeek    | wednesdayNextWeek
            mwfEvent | wednesdayNextWeek | fridayNextWeek
    }

    @Unroll("next occurence of weekly event with exclusion after #afterDate")
    def "test exclusion of next monday"() {
        setup:
            mwfEvent.addToExcludeDays(mondayNextWeek.toDate())

        expect:
            service.findNextOccurrence(event, afterDate.toDate()) == expectedResult.toDate()


        where:
            event    | afterDate           | expectedResult
            mwfEvent | now                 | wednesdayNextWeek
            mwfEvent | mondayNextWeek      | wednesdayNextWeek
            mwfEvent | wednesdayNextWeek   | fridayNextWeek

    }



}
Ok, so that’s pretty awesome and a lot more readable than the equivalent JUnit tests would be. I get 6 separate tests here with very little code. As expected it failed for weekly events without excluded days but worked fine if I exclude next monday:

image

Looks like I forgot a null check in my isOnExcludedDay method, so I modify that in my EventService:
    private def isOnExcludedDay(Event event, Date date) {
        date = (new DateTime(date)).withTime(0, 0, 0, 0).toDate()
        event.excludeDays?.contains(date)
    }
Now we’re golden:

image

As I continue learning about Spock I’ll add more tests, but so far I have to say writing Spock tests is a lot nicer than writing them in JUnit. Related:

Creating Google Calendar in Grails – Part 3: Creating and Modifying Events

Following up on Part 1 and Part 2 of this series where we created a model and rendered a Google calendar-like calendar. Now, finally we’ll finish things out by creating the actions and view that will allow us to view events as well as create and edit new events. Let’s start with by creating the tip balloon that shows the event title as well as the event time. Here’s what it looks like in Google Calendar:

image

One thing to keep in mind with this, is that for repeating events we want to show the particular event times for the particular day we clicked on. For example if we have an event that repeats on MWF and starts at the beginning of the month, if we click on the last Friday of the month it should display that particular date. So we need to pass the startTime of that particular occurrence to our show method. So here’s how we modify our calendar.js to do this:
 $("#calendar").fullCalendar({
        events: 'list.json',
        header: {
            left: 'prev,next today',
            center: 'title',
            right: 'month,agendaWeek,agendaDay'
        },
        eventRender: function(event, element) {
            $(element).addClass(event.cssClass);

            var occurrenceStart = event.start.getTime();
            var occurrenceEnd = event.end.getTime();

            var data = {id: event.id, occurrenceStart: occurrenceStart, occurrenceEnd: occurrenceEnd};

            $(element).qtip({
                content: {
                    text: ' ',
                    ajax: {
                        url: "show",
                        type: "GET",
                        data: data
                    }
                },
                show: {
                    event: 'click',
                    solo: true
                },
                hide: {
                    event: 'click'
                },
                style: {
                    width: '500px',
                    widget: true
                },
                position: {
                    my: 'bottom middle',
                    at: 'top middle',
                    viewport: true
                }
            });
        }
    });

Read More