diff --git a/kickstartWithBootstrap/KickstartWithBootstrapGrailsPlugin.groovy b/kickstartWithBootstrap/KickstartWithBootstrapGrailsPlugin.groovy
index 3c25b0c..6ba161c 100644
--- a/kickstartWithBootstrap/KickstartWithBootstrapGrailsPlugin.groovy
+++ b/kickstartWithBootstrap/KickstartWithBootstrapGrailsPlugin.groovy
@@ -1,6 +1,6 @@
class KickstartWithBootstrapGrailsPlugin {
// the plugin version
- def version = "0.8.1"
+ def version = "0.8.3"
// the version or versions of Grails the plugin is designed for
def grailsVersion = "2.0.0 > *"
// the other plugins this plugin depends on
diff --git a/kickstartWithBootstrap/README.mediawiki b/kickstartWithBootstrap/README.mediawiki
index e7ec071..d9fe19e 100644
--- a/kickstartWithBootstrap/README.mediawiki
+++ b/kickstartWithBootstrap/README.mediawiki
@@ -39,12 +39,6 @@ Affected files and directories (as of version 0.8.0; see script/Kickstart.groovy
* /views/index.gsp will be '''deleted'''!
* /views/error.gsp will be '''deleted'''!
-== Rare Problems ==
-During development and testing several strange error have emerged (they might be problems caused by the G&G Tool Suite - a restart of the GGTS helped me):
-
-* Sometimes the conf/URLmappings.groovy file is not copied by the Kickstart script into the conf directory of your project. If you run-app your project and get a 404 regarding the page "/WEB-INF/grails-app/views/index.jsp" you have to copy it yourself manually.
-* Sometimes the I18N files from the Kickstart plugin are not used. If you see I18N-codes such as "default.welcome.title" you have to copy the content of the I18N files into the property files in your project.
-
== Terms of Use ==
* Web Layout: [http://twitter.github.com/bootstrap/ Bootstrap 2.1], from Twitter Licensed under the Apache License v2.0. Documentation licensed under CC BY 3.0. (@TwBootstrap , http://twitter.github.com/bootstrap/)
@@ -56,6 +50,10 @@ During development and testing several strange error have emerged (they might be
== Changelog ==
+;0.8.3
+: Introduced a demo page with all fields used in the scaffolding process.
+;0.8.2
+: Corrected missing copy of resources.groovy.
;0.8.1
: Fixed error when copying UrlMappings.groovy, which was not packaged into the plugin.
;0.8.0
diff --git a/kickstartWithBootstrap/application.properties b/kickstartWithBootstrap/application.properties
index 51c894d..aee700a 100644
--- a/kickstartWithBootstrap/application.properties
+++ b/kickstartWithBootstrap/application.properties
@@ -1,26 +1,26 @@
#Grails Metadata file
-#Tue Oct 23 21:16:12 CEST 2012
+#Sat Oct 27 20:08:39 CEST 2012
app.grails.version=2.1.1
app.name=kickstartWithBootstrapGrailsPlugin
app.stats.Controllers.files=2
app.stats.Controllers.loc=90
app.stats.Domain_Classes.files=1
-app.stats.Domain_Classes.loc=12
+app.stats.Domain_Classes.loc=47
app.stats.Groovy_Helpers.files=1
app.stats.Groovy_Helpers.loc=10
app.stats.Scripts.files=5
-app.stats.Scripts.loc=122
+app.stats.Scripts.loc=134
app.stats.Tag_Libraries.files=1
app.stats.Tag_Libraries.loc=279
app.stats.Totals.files=12
-app.stats.Totals.loc=623
+app.stats.Totals.loc=670
app.stats.Unit_Tests.files=2
app.stats.Unit_Tests.loc=110
-app.version=0.8.1
-app.version.build=123
-app.version.build.date=Okt 23, 2012
+app.version=0.8.3
+app.version.build=150
+app.version.build.date=Okt 27, 2012
app.version.build.env=development
-app.version.revision=c59697e
+app.version.revision=ada1626
plugins.hibernate=2.1.1
plugins.jquery=1.8.0
plugins.lesscss-resources=1.3.0.3
diff --git a/kickstartWithBootstrap/grails-app/controllers/kickstartwithbootstrapgrailsplugin/_DemoPageController.groovy b/kickstartWithBootstrap/grails-app/controllers/kickstartwithbootstrapgrailsplugin/_DemoPageController.groovy
new file mode 100644
index 0000000..b9d00fc
--- /dev/null
+++ b/kickstartWithBootstrap/grails-app/controllers/kickstartwithbootstrapgrailsplugin/_DemoPageController.groovy
@@ -0,0 +1,107 @@
+package kickstartwithbootstrapgrailsplugin
+
+import org.springframework.dao.DataIntegrityViolationException
+
+/**
+ * _DemoPageController
+ * A controller class handles incoming web requests and performs actions such as redirects, rendering views and so on.
+ */
+class _DemoPageController {
+
+ static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
+
+ def index() {
+ redirect(action: "list", params: params)
+ }
+
+ def list() {
+ params.max = Math.min(params.max ? params.int('max') : 10, 100)
+ [_DemoPageInstanceList: _DemoPage.list(params), _DemoPageInstanceTotal: _DemoPage.count()]
+ }
+
+ def create() {
+ [_DemoPageInstance: new _DemoPage(params)]
+ }
+
+ def save() {
+ def _DemoPageInstance = new _DemoPage(params)
+ if (!_DemoPageInstance.save(flush: true)) {
+ render(view: "create", model: [_DemoPageInstance: _DemoPageInstance])
+ return
+ }
+
+ flash.message = message(code: 'default.created.message', args: [message(code: '_DemoPage.label', default: '_DemoPage'), _DemoPageInstance.id])
+ redirect(action: "show", id: _DemoPageInstance.id)
+ }
+
+ def show() {
+ def _DemoPageInstance = _DemoPage.get(params.id)
+ if (!_DemoPageInstance) {
+ flash.message = message(code: 'default.not.found.message', args: [message(code: '_DemoPage.label', default: '_DemoPage'), params.id])
+ redirect(action: "list")
+ return
+ }
+
+ [_DemoPageInstance: _DemoPageInstance]
+ }
+
+ def edit() {
+ def _DemoPageInstance = _DemoPage.get(params.id)
+ if (!_DemoPageInstance) {
+ flash.message = message(code: 'default.not.found.message', args: [message(code: '_DemoPage.label', default: '_DemoPage'), params.id])
+ redirect(action: "list")
+ return
+ }
+
+ [_DemoPageInstance: _DemoPageInstance]
+ }
+
+ def update() {
+ def _DemoPageInstance = _DemoPage.get(params.id)
+ if (!_DemoPageInstance) {
+ flash.message = message(code: 'default.not.found.message', args: [message(code: '_DemoPage.label', default: '_DemoPage'), params.id])
+ redirect(action: "list")
+ return
+ }
+
+ if (params.version) {
+ def version = params.version.toLong()
+ if (_DemoPageInstance.version > version) {
+ _DemoPageInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
+ [message(code: '_DemoPage.label', default: '_DemoPage')] as Object[],
+ "Another user has updated this _DemoPage while you were editing")
+ render(view: "edit", model: [_DemoPageInstance: _DemoPageInstance])
+ return
+ }
+ }
+
+ _DemoPageInstance.properties = params
+
+ if (!_DemoPageInstance.save(flush: true)) {
+ render(view: "edit", model: [_DemoPageInstance: _DemoPageInstance])
+ return
+ }
+
+ flash.message = message(code: 'default.updated.message', args: [message(code: '_DemoPage.label', default: '_DemoPage'), _DemoPageInstance.id])
+ redirect(action: "show", id: _DemoPageInstance.id)
+ }
+
+ def delete() {
+ def _DemoPageInstance = _DemoPage.get(params.id)
+ if (!_DemoPageInstance) {
+ flash.message = message(code: 'default.not.found.message', args: [message(code: '_DemoPage.label', default: '_DemoPage'), params.id])
+ redirect(action: "list")
+ return
+ }
+
+ try {
+ _DemoPageInstance.delete(flush: true)
+ flash.message = message(code: 'default.deleted.message', args: [message(code: '_DemoPage.label', default: '_DemoPage'), params.id])
+ redirect(action: "list")
+ }
+ catch (DataIntegrityViolationException e) {
+ flash.message = message(code: 'default.not.deleted.message', args: [message(code: '_DemoPage.label', default: '_DemoPage'), params.id])
+ redirect(action: "show", id: params.id)
+ }
+ }
+}
diff --git a/kickstartWithBootstrap/grails-app/domain/kickstartwithbootstrapgrailsplugin/_DemoPage.groovy b/kickstartWithBootstrap/grails-app/domain/kickstartwithbootstrapgrailsplugin/_DemoPage.groovy
new file mode 100644
index 0000000..834ec0e
--- /dev/null
+++ b/kickstartWithBootstrap/grails-app/domain/kickstartwithbootstrapgrailsplugin/_DemoPage.groovy
@@ -0,0 +1,84 @@
+package kickstartwithbootstrapgrailsplugin
+
+/**
+ * _DemoPage
+ * A domain class describes the data object and it's mapping to the database
+ */
+class _DemoPage {
+
+ /* Default (injected) attributes of GORM */
+// Long id
+// String version
+
+ String name = "The Demo Page"
+
+ // fields with special use (e.g., datepicker, new visual representation, etc.)
+ Date myDate
+ boolean myBoolean
+
+ // other fields used in the scaffolding process:
+ int myInt
+ short myShort
+ long myLong
+ float myFloat
+ double myDouble
+ byte myByte
+ char myChar
+
+ byte[] myByteArray
+// char[] myCharArray // Grails original URL scaffolding seems to have problems
+
+// URL myURL // Grails original URL scaffolding seems to have problems
+ Integer myInteger
+ TimeZone myTimeZone
+ Locale myLocale
+ Currency myCurrency
+
+ public enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES }
+ Suit myEnum
+
+ /* Automatic timestamping of GORM */
+ Date dateCreated
+ Date lastUpdated
+
+// static belongsTo = [] // tells GORM to cascade commands: e.g., delete this object if the "parent" is deleted.
+// static hasOne = [] // tells GORM to associate another domain object as an owner in a 1-1 mapping
+// static hasMany = [] // tells GORM to associate other domain objects for a 1-n or n-m mapping
+// static mappedBy = [] // specifies which property should be used in a mapping
+
+ static mapping = {
+ }
+
+ static constraints = {
+ // make all fields nullable to speed up demo usage (e.g., saves)
+ name nullable: true
+
+ myDate nullable: true
+ myBoolean nullable: true
+
+ myInt nullable: true
+ myShort nullable: true
+ myLong nullable: true
+ myFloat nullable: true
+ myDouble nullable: true
+ myByte nullable: true
+ myChar nullable: true
+
+ myByteArray nullable: true
+// myCharArray nullable: true
+
+// myURL nullable: true
+ myInteger nullable: true
+ myTimeZone nullable: true
+ myLocale nullable: true
+ myCurrency nullable: true
+ }
+
+ /*
+ * Methods of the Domain Class
+ */
+ @Override // Override toString for a nicer / more descriptive UI
+ public String toString() {
+ return "${name}";
+ }
+}
diff --git a/kickstartWithBootstrap/grails-app/i18n/messages.properties b/kickstartWithBootstrap/grails-app/i18n/messages.properties
index 9e55d6a..386f8c1 100644
--- a/kickstartWithBootstrap/grails-app/i18n/messages.properties
+++ b/kickstartWithBootstrap/grails-app/i18n/messages.properties
@@ -64,3 +64,5 @@ security.signoff.label = Sign out
checkbox.on.label = On
checkbox.off.label = Off
+
+default.date.format = yyyy-MM-dd
\ No newline at end of file
diff --git a/kickstartWithBootstrap/grails-app/i18n/messages_de.properties b/kickstartWithBootstrap/grails-app/i18n/messages_de.properties
index dfbcd91..e414f30 100644
--- a/kickstartWithBootstrap/grails-app/i18n/messages_de.properties
+++ b/kickstartWithBootstrap/grails-app/i18n/messages_de.properties
@@ -63,3 +63,5 @@ security.signoff.label = Ausloggen
checkbox.on.label = An
checkbox.off.label = Aus
+
+default.date.format = dd. MM. yyyy
diff --git a/kickstartWithBootstrap/grails-app/views/_DemoPage/_form.gsp b/kickstartWithBootstrap/grails-app/views/_DemoPage/_form.gsp
new file mode 100644
index 0000000..4ca8830
--- /dev/null
+++ b/kickstartWithBootstrap/grails-app/views/_DemoPage/_form.gsp
@@ -0,0 +1,132 @@
+<%@ page import="kickstartwithbootstrapgrailsplugin._DemoPage" %>
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'name', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myDate', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myBoolean', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myInt', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myShort', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myLong', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myFloat', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myDouble', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myByte', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myChar', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myByteArray', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myInteger', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myTimeZone', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myLocale', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myCurrency', 'error')}
+
+
+
+
+
+
+
+ ${hasErrors(bean: _DemoPageInstance, field: 'myEnum', 'error')}
+
+
+
diff --git a/kickstartWithBootstrap/grails-app/views/test/create.gsp b/kickstartWithBootstrap/grails-app/views/_DemoPage/create.gsp
similarity index 62%
rename from kickstartWithBootstrap/grails-app/views/test/create.gsp
rename to kickstartWithBootstrap/grails-app/views/_DemoPage/create.gsp
index ae3221d..281e502 100644
--- a/kickstartWithBootstrap/grails-app/views/test/create.gsp
+++ b/kickstartWithBootstrap/grails-app/views/_DemoPage/create.gsp
@@ -1,25 +1,25 @@
-<%@ page import="kickstartwithbootstrapgrailsplugin.Test" %>
+<%@ page import="kickstartwithbootstrapgrailsplugin._DemoPage" %>
-
+
-
+
-
+
-
+
-
+
diff --git a/kickstartWithBootstrap/grails-app/views/test/edit.gsp b/kickstartWithBootstrap/grails-app/views/_DemoPage/edit.gsp
similarity index 63%
rename from kickstartWithBootstrap/grails-app/views/test/edit.gsp
rename to kickstartWithBootstrap/grails-app/views/_DemoPage/edit.gsp
index 78b1046..3509251 100644
--- a/kickstartWithBootstrap/grails-app/views/test/edit.gsp
+++ b/kickstartWithBootstrap/grails-app/views/_DemoPage/edit.gsp
@@ -1,27 +1,27 @@
-<%@ page import="kickstartwithbootstrapgrailsplugin.Test" %>
+<%@ page import="kickstartwithbootstrapgrailsplugin._DemoPage" %>
-
+
-
+
-
+
-
+
-
-
-
+
+
+
diff --git a/kickstartWithBootstrap/grails-app/views/_DemoPage/list.gsp b/kickstartWithBootstrap/grails-app/views/_DemoPage/list.gsp
new file mode 100644
index 0000000..a86d2ce
--- /dev/null
+++ b/kickstartWithBootstrap/grails-app/views/_DemoPage/list.gsp
@@ -0,0 +1,61 @@
+
+<%@ page import="kickstartwithbootstrapgrailsplugin._DemoPage" %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${fieldValue(bean: _DemoPageInstance, field: "name")} |
+
+ |
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myInt")} |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myShort")} |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myLong")} |
+
+
+
+
+
+
+
+
+
+
+
diff --git a/kickstartWithBootstrap/grails-app/views/_DemoPage/show.gsp b/kickstartWithBootstrap/grails-app/views/_DemoPage/show.gsp
new file mode 100644
index 0000000..7ca29dc
--- /dev/null
+++ b/kickstartWithBootstrap/grails-app/views/_DemoPage/show.gsp
@@ -0,0 +1,150 @@
+
+<%@ page import="kickstartwithbootstrapgrailsplugin._DemoPage" %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "name")} |
+
+
+
+
+ |
+
+ |
+
+
+
+
+ |
+
+ |
+
+
+
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myInt")} |
+
+
+
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myShort")} |
+
+
+
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myLong")} |
+
+
+
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myFloat")} |
+
+
+
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myDouble")} |
+
+
+
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myByte")} |
+
+
+
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myChar")} |
+
+
+
+
+ |
+
+
+
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myInteger")} |
+
+
+
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myTimeZone")} |
+
+
+
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myLocale")} |
+
+
+
+
+ |
+
+ ${fieldValue(bean: _DemoPageInstance, field: "myCurrency")} |
+
+
+
+
+ |
+
+ |
+
+
+
+
+ |
+
+ |
+
+
+
+
+ |
+
+ ${_DemoPageInstance?.myEnum?.encodeAsHTML()} |
+
+
+
+
+
+
+
+
+
+
diff --git a/kickstartWithBootstrap/grails-app/views/test/_form.gsp b/kickstartWithBootstrap/grails-app/views/test/_form.gsp
deleted file mode 100644
index f4dd430..0000000
--- a/kickstartWithBootstrap/grails-app/views/test/_form.gsp
+++ /dev/null
@@ -1,27 +0,0 @@
-<%@ page import="kickstartwithbootstrapgrailsplugin.Test" %>
-
-
-
-
-
-
- ${hasErrors(bean: testInstance, field: 'isGrailsUser', 'error')}
-
-
-
-
-
-
-
- ${hasErrors(bean: testInstance, field: 'birthday', 'error')}
-
-
-
-
-
-
-
- ${hasErrors(bean: testInstance, field: 'name', 'error')}
-
-
-
diff --git a/kickstartWithBootstrap/grails-app/views/test/list.gsp b/kickstartWithBootstrap/grails-app/views/test/list.gsp
deleted file mode 100644
index 82d8406..0000000
--- a/kickstartWithBootstrap/grails-app/views/test/list.gsp
+++ /dev/null
@@ -1,49 +0,0 @@
-
-<%@ page import="kickstartwithbootstrapgrailsplugin.Test" %>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${fieldValue(bean: testInstance, field: "birthday")} |
-
- |
-
- ${fieldValue(bean: testInstance, field: "name")} |
-
-
-
-
-
-
-
-
-
-
-
diff --git a/kickstartWithBootstrap/grails-app/views/test/show.gsp b/kickstartWithBootstrap/grails-app/views/test/show.gsp
deleted file mode 100644
index bb9dcc7..0000000
--- a/kickstartWithBootstrap/grails-app/views/test/show.gsp
+++ /dev/null
@@ -1,47 +0,0 @@
-
-<%@ page import="kickstartwithbootstrapgrailsplugin.Test" %>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- |
-
- |
-
-
-
-
- |
-
- |
-
-
-
-
- |
-
- ${fieldValue(bean: testInstance, field: "name")} |
-
-
-
-
-
-
-
-
-
-
diff --git a/kickstartWithBootstrap/plugin.xml b/kickstartWithBootstrap/plugin.xml
index 5cceaa9..605db3c 100644
--- a/kickstartWithBootstrap/plugin.xml
+++ b/kickstartWithBootstrap/plugin.xml
@@ -1,4 +1,4 @@
-
+
Joerg Rech
joerg.rech@gmail.com
Kickstart with Bootstrap - Good looking websites!
@@ -10,8 +10,8 @@
kickstart.KickstartFilters
spring.resources
HomeController
- kickstartwithbootstrapgrailsplugin.TestController
- kickstartwithbootstrapgrailsplugin.Test
+ kickstartwithbootstrapgrailsplugin._DemoPageController
+ kickstartwithbootstrapgrailsplugin._DemoPage
kickstart.BootstrapTagLib
diff --git a/kickstartWithBootstrap/scripts/Kickstart.groovy b/kickstartWithBootstrap/scripts/Kickstart.groovy
index c48ded2..7d0cec7 100644
--- a/kickstartWithBootstrap/scripts/Kickstart.groovy
+++ b/kickstartWithBootstrap/scripts/Kickstart.groovy
@@ -14,12 +14,13 @@ def deleteAll = false
target(kickstart: "Installs the Kickstart scaffolding templates and other files") {
depends(checkVersion, parseArguments)
- event "StatusUpdate", ['\nNOTE: execution in eclipse (STS, GGTS) might result in the erroneous messages "Invalid input. Must be one of"! Just ignore them!\n']
+ event "StatusUpdate", ['\nNOTE: execution in eclipse (STS, GGTS) might result in the erroneous messages "Invalid input. Must be one of" --> Just ignore them!\n']
sourceDir = "${kickstartWithBootstrapPluginDir}/src"
targetDir = "${basedir}/grails-app/conf/"
- copy("${sourceDir}/UrlMappings.groovy", targetDir, "URLMappings.groovy", code)
-
+ copy("${sourceDir}/UrlMappings.groovy", targetDir, "URLMappings.groovy", code)
+ copy("${sourceDir}/resources.groovy", targetDir+"spring/","resources.groovy", code)
+
// copy less files into project
sourceDir = "${kickstartWithBootstrapPluginDir}/web-app/less"
targetDir = "${basedir}/web-app/less"
diff --git a/kickstartWithBootstrap/test/unit/kickstartwithbootstrapgrailsplugin/_DemoPageControllerTests.groovy b/kickstartWithBootstrap/test/unit/kickstartwithbootstrapgrailsplugin/_DemoPageControllerTests.groovy
new file mode 100644
index 0000000..83dc003
--- /dev/null
+++ b/kickstartWithBootstrap/test/unit/kickstartwithbootstrapgrailsplugin/_DemoPageControllerTests.groovy
@@ -0,0 +1,163 @@
+package kickstartwithbootstrapgrailsplugin
+
+
+
+import org.junit.*
+import grails.test.mixin.*
+
+/**
+ * _DemoPageControllerTests
+ * A unit test class is used to test individual methods or blocks of code without considering the surrounding infrastructure
+ */
+@TestFor(_DemoPageController)
+@Mock(_DemoPage)
+class _DemoPageControllerTests {
+
+
+ def populateValidParams(params) {
+ assert params != null
+ // TODO: Populate valid properties like...
+ //params["name"] = 'someValidName'
+ }
+
+ void testIndex() {
+ controller.index()
+ assert "/_DemoPage/list" == response.redirectedUrl
+ }
+
+ void testList() {
+
+ def model = controller.list()
+
+ assert model._DemoPageInstanceList.size() == 0
+ assert model._DemoPageInstanceTotal == 0
+ }
+
+ void testCreate() {
+ def model = controller.create()
+
+ assert model._DemoPageInstance != null
+ }
+
+ void testSave() {
+ controller.save()
+
+ assert model._DemoPageInstance != null
+ assert view == '/_DemoPage/create'
+
+ response.reset()
+
+ populateValidParams(params)
+ controller.save()
+
+ assert response.redirectedUrl == '/_DemoPage/show/1'
+ assert controller.flash.message != null
+ assert _DemoPage.count() == 1
+ }
+
+ void testShow() {
+ controller.show()
+
+ assert flash.message != null
+ assert response.redirectedUrl == '/_DemoPage/list'
+
+
+ populateValidParams(params)
+ def _DemoPage = new _DemoPage(params)
+
+ assert _DemoPage.save() != null
+
+ params.id = _DemoPage.id
+
+ def model = controller.show()
+
+ assert model._DemoPageInstance == _DemoPage
+ }
+
+ void testEdit() {
+ controller.edit()
+
+ assert flash.message != null
+ assert response.redirectedUrl == '/_DemoPage/list'
+
+
+ populateValidParams(params)
+ def _DemoPage = new _DemoPage(params)
+
+ assert _DemoPage.save() != null
+
+ params.id = _DemoPage.id
+
+ def model = controller.edit()
+
+ assert model._DemoPageInstance == _DemoPage
+ }
+
+ void testUpdate() {
+ controller.update()
+
+ assert flash.message != null
+ assert response.redirectedUrl == '/_DemoPage/list'
+
+ response.reset()
+
+
+ populateValidParams(params)
+ def _DemoPage = new _DemoPage(params)
+
+ assert _DemoPage.save() != null
+
+ // test invalid parameters in update
+ params.id = _DemoPage.id
+ //TODO: add invalid values to params object
+
+ controller.update()
+
+ assert view == "/_DemoPage/edit"
+ assert model._DemoPageInstance != null
+
+ _DemoPage.clearErrors()
+
+ populateValidParams(params)
+ controller.update()
+
+ assert response.redirectedUrl == "/_DemoPage/show/$_DemoPage.id"
+ assert flash.message != null
+
+ //test outdated version number
+ response.reset()
+ _DemoPage.clearErrors()
+
+ populateValidParams(params)
+ params.id = _DemoPage.id
+ params.version = -1
+ controller.update()
+
+ assert view == "/_DemoPage/edit"
+ assert model._DemoPageInstance != null
+ assert model._DemoPageInstance.errors.getFieldError('version')
+ assert flash.message != null
+ }
+
+ void testDelete() {
+ controller.delete()
+ assert flash.message != null
+ assert response.redirectedUrl == '/_DemoPage/list'
+
+ response.reset()
+
+ populateValidParams(params)
+ def _DemoPage = new _DemoPage(params)
+
+ assert _DemoPage.save() != null
+ assert _DemoPage.count() == 1
+
+ params.id = _DemoPage.id
+
+ controller.delete()
+
+ assert _DemoPage.count() == 0
+ assert _DemoPage.get(_DemoPage.id) == null
+ assert response.redirectedUrl == '/_DemoPage/list'
+ }
+}
diff --git a/kickstartWithBootstrap/test/unit/kickstartwithbootstrapgrailsplugin/_DemoPageTests.groovy b/kickstartWithBootstrap/test/unit/kickstartwithbootstrapgrailsplugin/_DemoPageTests.groovy
new file mode 100644
index 0000000..1a6d003
--- /dev/null
+++ b/kickstartWithBootstrap/test/unit/kickstartwithbootstrapgrailsplugin/_DemoPageTests.groovy
@@ -0,0 +1,17 @@
+package kickstartwithbootstrapgrailsplugin
+
+
+
+import grails.test.mixin.*
+import org.junit.*
+
+/**
+ * See the API for {@link grails.test.mixin.domain.DomainClassUnitTestMixin} for usage instructions
+ */
+@TestFor(_DemoPage)
+class _DemoPageTests {
+
+ void testSomething() {
+ fail "Implement me"
+ }
+}