Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1959 from ReviakinAleksey/fix_crudify_render_all
Fix crudify render all Template rendered for crud.all Snippet in net.liftweb.proto.Crudify renders empty td elements instead of TheCrudType filed values. This PR introduce issue fix and test for this functionality.
- Loading branch information
Showing
4 changed files
with
211 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -281,3 +281,6 @@ Henrik Härkönen | |
|
||
### Email: ### | ||
heharkon@iki.fi | ||
|
||
### Email: ### | ||
it dot blackdog at gmail dot com |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 110 additions & 0 deletions
110
persistence/proto/src/test/scala/net/liftweb/CrudifySpec.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package net.liftweb | ||
|
||
import net.liftweb.common.{Box, Full} | ||
import net.liftweb.fixtures._ | ||
import net.liftweb.http.{Req, S} | ||
import net.liftweb.proto.Crudify | ||
import net.liftweb.util.{BaseField, FieldError, LiftValue} | ||
import org.specs2.matcher.XmlMatchers | ||
import org.specs2.mutable.Specification | ||
import org.specs2.specification.Scope | ||
|
||
import scala.xml.{NodeSeq, Text} | ||
|
||
object CrudifySpec extends Specification with XmlMatchers { | ||
"Crudify Trait Specification".title | ||
|
||
/** Spec class implementation of [[net.liftweb.proto.Crudify]] trait */ | ||
trait SpecCrudify extends Crudify { | ||
|
||
def repo: SpecCrudRepo | ||
|
||
override type TheCrudType = SpecCrudType | ||
|
||
override type FieldPointerType = SpecCrudType.FieldType | ||
|
||
|
||
override def calcPrefix: List[String] = List("Prefix") | ||
|
||
override def create: SpecCrudType = new SpecCrudType("", "") | ||
|
||
override def fieldsForDisplay: List[FieldPointerType] = SpecCrudType.FIELDS | ||
|
||
override def findForList(start: Long, count: Int): List[TheCrudType] = repo.all | ||
|
||
override def findForParam(in: String): Box[TheCrudType] = repo.find(in) | ||
|
||
|
||
override protected implicit def buildBridge(from: TheCrudType): CrudBridge = new CrudBridge { | ||
|
||
override def delete_! : Boolean = repo.delete_!(from) | ||
|
||
|
||
override def save: Boolean = repo.save(from) | ||
|
||
override def validate: List[FieldError] = repo.validate(from) | ||
|
||
|
||
override def primaryKeyFieldAsString: String = repo.primaryKeyFieldAsString(from) | ||
} | ||
|
||
override protected implicit def buildFieldBridge(from: FieldPointerType): FieldPointerBridge = new FieldPointerBridge { | ||
override def displayHtml: NodeSeq = from.displayHtml | ||
} | ||
|
||
override protected def computeFieldFromPointer(instance: TheCrudType, pointer: FieldPointerType): Box[BaseField] = { | ||
val result: BaseField = new BaseField with LiftValue[String] { | ||
override def setFilter: List[String => String] = Nil | ||
|
||
override def validations: List[String => List[FieldError]] = Nil | ||
|
||
override def validate: List[FieldError] = Nil | ||
|
||
override def toForm: Box[NodeSeq] = Full(Text(get)) | ||
|
||
override def name: String = pointer.fieldName | ||
|
||
override def set(in: String): String = { | ||
pointer.setter(instance, in) | ||
in | ||
} | ||
|
||
override def get: String = pointer.getter(instance) | ||
} | ||
Full(result) | ||
} | ||
} | ||
|
||
"Crudify `showAllTemplate`" should { | ||
|
||
class SpecCrudifyWithContext extends SpecCrudify with Scope { | ||
val repo: SpecCrudRepo = SpecCrudType.defaultRepo | ||
|
||
def all: NodeSeq = S.statelessInit(Req.nil)({ | ||
doCrudAll(this.showAllTemplate()) | ||
}) | ||
|
||
} | ||
|
||
"render proper rows count" in new SpecCrudifyWithContext { | ||
all \\ "tbody" \\ "tr" must have size repo.size | ||
} | ||
|
||
"render proper headers content" in new SpecCrudifyWithContext { | ||
val th: NodeSeq = all \\ "thead" \\ "th" | ||
val renderedHeaders = th.map(_.text).filterNot(_ == " ") | ||
renderedHeaders must contain(exactly(SpecCrudType.FIELDS.map(_.fieldName): _*)) | ||
} | ||
|
||
"render proper colums content" in new SpecCrudifyWithContext { | ||
val tr: NodeSeq = all \\ "tbody" \\ "tr" | ||
val renderedValues: List[List[String]] = tr.map(row => { | ||
(row \ "td") | ||
.filter(td => (td \ "@class").nonEmpty) | ||
.map(_.text).toList | ||
}).toList | ||
val expectedValues: List[List[String]] = repo.all.map(i => List(i.id, i.value)) | ||
renderedValues === expectedValues | ||
} | ||
} | ||
} |
97 changes: 97 additions & 0 deletions
97
persistence/proto/src/test/scala/net/liftweb/fixtures/Fixtures.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package net.liftweb | ||
package fixtures | ||
|
||
import net.liftweb.common.Box | ||
import net.liftweb.util.FieldError | ||
|
||
import scala.collection.mutable | ||
import scala.xml.{NodeSeq, Text} | ||
|
||
/** | ||
* Helper type represents content for [[net.liftweb.proto.Crudify]] | ||
* | ||
* @param id fake data `id` field | ||
* @param value fake data `value` field | ||
*/ | ||
class SpecCrudType(var id: String, var value: String) | ||
|
||
/** Helper object for [[net.liftweb.proto.Crudify]] trait testing */ | ||
object SpecCrudType { | ||
/** [[net.liftweb.proto.Crudify.FieldPointerType]] */ | ||
type FieldType = SpecField[SpecCrudType] | ||
|
||
/** Default initial [[SpecCrudRepo]] content */ | ||
val DEFAULT_REPO_CONTENT = List("1" -> new SpecCrudType("1", "first"), | ||
"2" -> new SpecCrudType("2", "second"), | ||
"3" -> new SpecCrudType("3", "third")) | ||
|
||
/** Default fields for [[SpecCrudType]] */ | ||
val FIELDS: List[FieldType] = List( | ||
SpecField("id", _.id, (h, v) => h.id = v), | ||
SpecField("value", _.value, (h, v) => h.value = v)) | ||
|
||
/** Build [[SpecCrudRepo]] with default content */ | ||
def defaultRepo: SpecCrudRepo = new SpecCrudRepo(DEFAULT_REPO_CONTENT: _*) | ||
} | ||
|
||
/** | ||
* Helper type witch should be used as [[net.liftweb.proto.Crudify.FieldPointerType]] | ||
* | ||
* @param fieldName fake date field na,e | ||
* @param getter return `fieldName` value as [[String]] from [[T]] instance | ||
* @param setter convert given [[String]] and it as set `fieldName` value in [[T]] instance | ||
* @tparam T target fake data holder type ([[SpecCrudType]] for now) | ||
*/ | ||
case class SpecField[T](fieldName: String, getter: T => String, setter: (T, String) => Unit) { | ||
|
||
/** | ||
* Field name as HTML | ||
* | ||
* @return Element with represents field name in HTML | ||
*/ | ||
def displayHtml: NodeSeq = Text(fieldName) | ||
} | ||
|
||
|
||
/** | ||
* Helper class for creating fake data repository for using as [[net.liftweb.proto.Crudify.CrudBridge]] and for others | ||
* methods needed by [[net.liftweb.proto.Crudify]] implementation | ||
* | ||
* @param initalContent initial content for repor | ||
*/ | ||
class SpecCrudRepo(initalContent: (String, SpecCrudType)*) { | ||
private val dict: mutable.Map[String, SpecCrudType] = mutable.LinkedHashMap(initalContent: _*) | ||
|
||
/** Return items count in repo */ | ||
def size: Int = dict.size | ||
|
||
/** Return repo content */ | ||
//TODO: support for pagination | ||
def all: List[SpecCrudType] = dict.values.toList | ||
|
||
/** Find content in repo by [[String]] `id` param */ | ||
def find(id: String): Box[SpecCrudType] = { | ||
dict.get(id) | ||
} | ||
|
||
/** Delete content from repo */ | ||
def delete_!(target: SpecCrudType): Boolean = { | ||
dict.remove(target.id).isDefined | ||
} | ||
|
||
/** Save new instance to repo or replcace previous value inside repo if present */ | ||
def save(target: SpecCrudType): Boolean = { | ||
dict += target.id -> target | ||
true | ||
} | ||
|
||
/** Validate instance */ | ||
def validate(target: SpecCrudType): List[FieldError] = Nil | ||
|
||
|
||
/** Return [[String]] representation of instance primary field */ | ||
def primaryKeyFieldAsString(target: SpecCrudType): String = target.id | ||
} | ||
|
||
|
||
|