-
Notifications
You must be signed in to change notification settings - Fork 73
tests for scaffold.Document #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # the heading | ||
|
|
||
| And the lead |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # first/title | ||
|
|
||
| LEAD | ||
|
|
||
|
|
||
|
|
||
| # section 1 | ||
| Body1 | ||
| # Sec B | ||
|
|
||
|
|
||
|
|
||
| Second body | ||
|
|
||
|
|
||
| # Part III | ||
|
|
||
| A section | ||
| be here |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| no heading |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| # only heading |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # With some code | ||
|
|
||
| # code section | ||
|
|
||
| Code preface | ||
|
|
||
| var actual_code = 0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| package com.twitter.scaffold | ||
|
|
||
| import org.scalatest.WordSpec | ||
| import org.scalatest.matchers.MustMatchers | ||
| import com.twitter.scaffold.Document | ||
| import DocumentSpecHelpers._ | ||
|
|
||
| class DocumentSpec extends WordSpec with MustMatchers { | ||
| def render(name: String) = Document.render(name) | ||
| def getHtml(name: String): String = render(name).get.toString | ||
|
|
||
| "Document.render" should { | ||
| "return None for non-existent data file" in { | ||
| render("not_a_file") must equal (None) | ||
| } | ||
|
|
||
| "return None for empty data file" in { | ||
| render("empty") must equal (None) | ||
| } | ||
|
|
||
| "return None for a file not starting with a heading" in { | ||
| render("no_heading") must equal (None) | ||
| } | ||
| } | ||
|
|
||
| "Document.render" can { | ||
| "render a file with only a heading" in { | ||
| val xml = parse(getHtml("only_heading")) | ||
| title(xml) must equal ("Scala School 2 - only heading") | ||
| firstHeading(xml) must equal ("only heading") | ||
| lead(xml) must equal ("") | ||
| } | ||
|
|
||
| "render a heading and lead" in { | ||
| val xml = parse(getHtml("heading_with_lead")) | ||
| title(xml) must equal ("Scala School 2 - the heading") | ||
| firstHeading(xml) must equal ("the heading") | ||
| lead(xml) must equal ("And the lead") | ||
| } | ||
|
|
||
| "render multiple headings" in { | ||
| val xml = parse(getHtml("multiple_headings")) | ||
| title(xml) must equal ("Scala School 2 - first/title") | ||
| firstHeading(xml) must equal ("first/title") | ||
| lead(xml) must equal ("LEAD") | ||
| toc(xml) must equal ( | ||
| List( | ||
| ("section 1", "#section-1"), | ||
| ("Sec B", "#sec-b"), | ||
| ("Part III", "#part-iii") | ||
| ) | ||
| ) | ||
| sections(xml) must equal ( | ||
| List( | ||
| ("section-1", "section 1", "<p>Body1</p>"), | ||
| ("sec-b", "Sec B", "<p>Second body</p>"), | ||
| ("part-iii", "Part III", "<p>A section<br/>be here</p>") | ||
| ) | ||
| ) | ||
| } | ||
|
|
||
| "render code segments" in { | ||
| val xml = parse(getHtml("with_code")) | ||
| toc(xml).head must equal (("code section", "#code-section")) | ||
| sections(xml).head must equal (("code-section", "code section", "<p>Code preface</p><textarea>var actual_code = 0\n</textarea>")) | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| package com.twitter.scaffold | ||
|
|
||
| import scala.xml._ | ||
|
|
||
| object DocumentSpecHelpers { | ||
| def parse(html: String) = XML.loadString(html) | ||
|
|
||
| def title(xml: Elem): String = { | ||
| xml.child.find { | ||
| _.label == "head" | ||
| } flatMap { | ||
| _.child.find(_.label == "title") | ||
| } map { | ||
| _.text | ||
| } getOrElse "" | ||
| } | ||
|
|
||
| def firstHeading(xml: Elem): String = { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same trick here. The pattern you can recognize is: a sequence of |
||
| xml.child.find { | ||
| _.label == "body" | ||
| } flatMap { | ||
| _.child.find(_.label == "header") | ||
| } flatMap { | ||
| _.child.find(_.label == "div") | ||
| } flatMap { | ||
| _.child.find(_.label == "h1") | ||
| } map { | ||
| _.text | ||
| } getOrElse "" | ||
| } | ||
|
|
||
| def lead(xml: Elem): String = { | ||
| xml.child.find { | ||
| _.label == "body" | ||
| } flatMap { | ||
| _.child.find(_.label == "header") | ||
| } flatMap { | ||
| _.child.find(_.label == "div") | ||
| } flatMap { | ||
| _.child.find(_.label == "p") | ||
| } map { | ||
| _.text | ||
| } getOrElse "" | ||
| } | ||
|
|
||
| def toc(xml: Elem): List[(String, String)] = { | ||
| xml.child.find { | ||
| _.label == "body" | ||
| } flatMap { | ||
| _.child.find { n: Node => | ||
| n.label == "div" && n.attributes("class") != null && n.attributes("class").head.text == "span3 scaffold-sidebar" | ||
| } | ||
| } flatMap { | ||
| _.child.find(_.label == "ul") | ||
| } map { | ||
| _.child.toList.filter(_.label == "li") map { n: Node => | ||
| val c = n.child.find(_.label == "a").get | ||
| (c.text.tail, c.attributes("href").head.text) | ||
| } | ||
| } getOrElse List() | ||
| } | ||
|
|
||
| def sections(xml: Elem): List[(String, String, String)] = { | ||
| xml.child.find { | ||
| _.label == "body" | ||
| } flatMap { | ||
| _.child.find { n: Node => | ||
| n.label == "div" && n.attributes("class") != null && n.attributes("class").head.text == "container" | ||
| } | ||
| } map { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one's a slightly different situation: if you have two chained calls to Although it'd probably be better here to split it up like: |
||
| _.child(1).child(1) | ||
| } map { | ||
| _.child.toList.filter(_.label == "section") map { n: Node => | ||
| val link = n.attributes("id").head.text | ||
| val header = n.child(1).child(0).text | ||
| val rest = n.child.tail.tail.mkString("").trim | ||
| (link, header, rest) | ||
| } | ||
| } getOrElse List() | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than explicitly doing
flatMapandmap, you can do this a bit more idiomatically usingfor-expressions:And probably shouldn't do the
getOrElse "", to avoid masking errors in the tests.