Index: branches/features/purchaseOrders/test/functional/LoginSpec.groovy
===================================================================
--- branches/features/purchaseOrders/test/functional/LoginSpec.groovy	(revision 938)
+++ branches/features/purchaseOrders/test/functional/LoginSpec.groovy	(revision 947)
@@ -1,4 +1,5 @@
 import gnumims.functional.pages.HomePage
 import gnumims.functional.pages.LoginPage
+import gnumims.functional.pages.LogoutPage
 import spock.lang.Stepwise
 
@@ -8,8 +9,8 @@
     def "We start at the login page"() {
         when:
-        go getBaseUrl()
+        go baseUrl
 
         then:
-        $("h1").text() == "Welcome to gnuMims please log in"
+        at LoginPage
     }
 
@@ -19,17 +20,17 @@
         form.j_username = "admin"
         form.j_password = "pass"
-        login.click(HomePage)
+        login.click()
 
         then:
-        at(HomePage)
+        at HomePage
     }
 
-    def "When we click logout, we go back to the login page"() {
+    def "When we click logout, we go to the logout page"() {
         when:
-        to HomePage
         logout.click()
 
         then:
-        at(LoginPage)
+        at LogoutPage
+        verifyLogoutMessage()
     }
 
@@ -39,8 +40,9 @@
         form.j_username = "admin"
         form.j_password = "bogus"
-        login.click(LoginPage)
+        login.click()
 
         then:
-        $("div.login_message").text() == "[admin] wrong username/password."
+        at LoginPage
+        verifyLoginFailureMessage()
     }
 
Index: branches/features/purchaseOrders/test/functional/gnumims/functional/pages/GrailsPage.groovy
===================================================================
--- branches/features/purchaseOrders/test/functional/gnumims/functional/pages/GrailsPage.groovy	(revision 947)
+++ branches/features/purchaseOrders/test/functional/gnumims/functional/pages/GrailsPage.groovy	(revision 947)
@@ -0,0 +1,44 @@
+package gnumims.functional.pages
+
+import geb.Page
+
+/**
+ * http://ldaley.com/post/1013531080/painless-page-identification-with-geb-grails
+ */
+abstract class GrailsPage extends Page {
+
+    // To be overridden by subclasses
+    static controller = null
+    static action = null
+    static url = "$controller/$action"
+
+    static at = {
+        // delegate here is the original page _instance_ (i.e. the subclass)
+
+        def expectedPageControllerName = delegate.class.controller
+        if (expectedPageControllerName == null) {
+            throw new IllegalStateException("${delegate.class} forgot to declare which controller it belongs to")
+        }
+
+        def expectedPageActionName = delegate.class.action
+        if (expectedPageActionName == null) {
+            throw new IllegalStateException("${delegate.class} forgot to declare which action it is")
+        }
+
+        def actualPageControllerName = controllerName
+        def actualPageActionName = actionName
+
+        assert actualPageControllerName == expectedPageControllerName
+        assert actualPageActionName == expectedPageActionName
+
+        true // at checkers must return true
+    }
+
+    static content = {
+        pageId { $("meta", name: "pageId").@content }
+        controllerName { pageId.split('\\.')[0] }
+        actionName { pageId.split('\\.')[1] }
+    }
+
+}
+
Index: branches/features/purchaseOrders/test/functional/gnumims/functional/pages/HomePage.groovy
===================================================================
--- branches/features/purchaseOrders/test/functional/gnumims/functional/pages/HomePage.groovy	(revision 938)
+++ branches/features/purchaseOrders/test/functional/gnumims/functional/pages/HomePage.groovy	(revision 947)
@@ -1,14 +1,11 @@
 package gnumims.functional.pages
 
-import geb.Page
-
-class HomePage extends Page {
-    static url = "appCore/start"
-
-    static at = { $("div#menu li.navigation_active").text() == "Home" }
+class HomePage extends GrailsPage {
+    static controller = "appCore"
+    static action = "start"
 
     static content = {
         message { $("div.body div.message").text() }
-        logout(to:LoginPage) { $("a[class=logoutButton]") }
+        logout(to:LogoutPage) { $("a[class=logoutButton]") }
     }
 }
Index: branches/features/purchaseOrders/test/functional/gnumims/functional/pages/LoginPage.groovy
===================================================================
--- branches/features/purchaseOrders/test/functional/gnumims/functional/pages/LoginPage.groovy	(revision 938)
+++ branches/features/purchaseOrders/test/functional/gnumims/functional/pages/LoginPage.groovy	(revision 947)
@@ -1,15 +1,18 @@
 package gnumims.functional.pages
 
-import geb.Page
-
-class LoginPage extends Page {
-    static url = "login/auth"
-
-    static at = {$("h1").text() == "Welcome to gnuMims please log in"}
+class LoginPage extends GrailsPage {
+    static controller = "login"
+    static action = "auth"
 
     static content = {
-        login { $('#loginForm input[value=Login]') }
+        login(to:HomePage) { $('#loginForm input[value=Login]') }
         form { $("#loginForm") }
         password { $("input[name=j_password]").value() }
+        message { $("div.login_message").text() }
+    }
+
+    def verifyLoginFailureMessage() {
+        assert message.contains("wrong username/password.")
+        return true
     }
 }
Index: branches/features/purchaseOrders/test/functional/gnumims/functional/pages/LogoutPage.groovy
===================================================================
--- branches/features/purchaseOrders/test/functional/gnumims/functional/pages/LogoutPage.groovy	(revision 947)
+++ branches/features/purchaseOrders/test/functional/gnumims/functional/pages/LogoutPage.groovy	(revision 947)
@@ -0,0 +1,15 @@
+package gnumims.functional.pages
+
+class LogoutPage extends GrailsPage {
+    static controller = "login"
+    static action = "loggedOut"
+
+    static content = {
+        message { $("div.login_message").text() }
+    }
+
+    def verifyLogoutMessage() {
+        assert message == "Successfully logged out"
+        return true
+    }
+}
