hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

content_test.go (8036B)

    1 // Copyright 2019 The Hugo Authors. All rights reserved.
    2 //
    3 // Licensed under the Apache License, Version 2.0 (the "License");
    4 // you may not use this file except in compliance with the License.
    5 // You may obtain a copy of the License at
    6 // http://www.apache.org/licenses/LICENSE-2.0
    7 //
    8 // Unless required by applicable law or agreed to in writing, software
    9 // distributed under the License is distributed on an "AS IS" BASIS,
   10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   11 // See the License for the specific language governing permissions and
   12 // limitations under the License.
   13 
   14 package helpers
   15 
   16 import (
   17 	"bytes"
   18 	"html/template"
   19 	"strings"
   20 	"testing"
   21 
   22 	"github.com/spf13/afero"
   23 
   24 	"github.com/gohugoio/hugo/common/loggers"
   25 	"github.com/gohugoio/hugo/config"
   26 
   27 	qt "github.com/frankban/quicktest"
   28 )
   29 
   30 const tstHTMLContent = "<!DOCTYPE html><html><head><script src=\"http://two/foobar.js\"></script></head><body><nav><ul><li hugo-nav=\"section_0\"></li><li hugo-nav=\"section_1\"></li></ul></nav><article>content <a href=\"http://two/foobar\">foobar</a>. Follow up</article><p>This is some text.<br>And some more.</p></body></html>"
   31 
   32 func TestTrimShortHTML(t *testing.T) {
   33 	tests := []struct {
   34 		input, output []byte
   35 	}{
   36 		{[]byte(""), []byte("")},
   37 		{[]byte("Plain text"), []byte("Plain text")},
   38 		{[]byte("  \t\n Whitespace text\n\n"), []byte("Whitespace text")},
   39 		{[]byte("<p>Simple paragraph</p>"), []byte("Simple paragraph")},
   40 		{[]byte("\n  \n \t  <p> \t Whitespace\nHTML  \n\t </p>\n\t"), []byte("Whitespace\nHTML")},
   41 		{[]byte("<p>Multiple</p><p>paragraphs</p>"), []byte("<p>Multiple</p><p>paragraphs</p>")},
   42 		{[]byte("<p>Nested<p>paragraphs</p></p>"), []byte("<p>Nested<p>paragraphs</p></p>")},
   43 		{[]byte("<p>Hello</p>\n<ul>\n<li>list1</li>\n<li>list2</li>\n</ul>"), []byte("<p>Hello</p>\n<ul>\n<li>list1</li>\n<li>list2</li>\n</ul>")},
   44 	}
   45 
   46 	c := newTestContentSpec()
   47 	for i, test := range tests {
   48 		output := c.TrimShortHTML(test.input)
   49 		if !bytes.Equal(test.output, output) {
   50 			t.Errorf("Test %d failed. Expected %q got %q", i, test.output, output)
   51 		}
   52 	}
   53 }
   54 
   55 func TestStripEmptyNav(t *testing.T) {
   56 	c := qt.New(t)
   57 	cleaned := stripEmptyNav([]byte("do<nav>\n</nav>\n\nbedobedo"))
   58 	c.Assert(cleaned, qt.DeepEquals, []byte("dobedobedo"))
   59 }
   60 
   61 func TestBytesToHTML(t *testing.T) {
   62 	c := qt.New(t)
   63 	c.Assert(BytesToHTML([]byte("dobedobedo")), qt.Equals, template.HTML("dobedobedo"))
   64 }
   65 
   66 func TestNewContentSpec(t *testing.T) {
   67 	cfg := config.NewWithTestDefaults()
   68 	c := qt.New(t)
   69 
   70 	cfg.Set("summaryLength", 32)
   71 	cfg.Set("buildFuture", true)
   72 	cfg.Set("buildExpired", true)
   73 	cfg.Set("buildDrafts", true)
   74 
   75 	spec, err := NewContentSpec(cfg, loggers.NewErrorLogger(), afero.NewMemMapFs(), nil)
   76 
   77 	c.Assert(err, qt.IsNil)
   78 	c.Assert(spec.summaryLength, qt.Equals, 32)
   79 	c.Assert(spec.BuildFuture, qt.Equals, true)
   80 	c.Assert(spec.BuildExpired, qt.Equals, true)
   81 	c.Assert(spec.BuildDrafts, qt.Equals, true)
   82 }
   83 
   84 var benchmarkTruncateString = strings.Repeat("This is a sentence about nothing.", 20)
   85 
   86 func BenchmarkTestTruncateWordsToWholeSentence(b *testing.B) {
   87 	c := newTestContentSpec()
   88 	b.ResetTimer()
   89 	for i := 0; i < b.N; i++ {
   90 		c.TruncateWordsToWholeSentence(benchmarkTruncateString)
   91 	}
   92 }
   93 
   94 func BenchmarkTestTruncateWordsToWholeSentenceOld(b *testing.B) {
   95 	c := newTestContentSpec()
   96 	b.ResetTimer()
   97 	for i := 0; i < b.N; i++ {
   98 		c.truncateWordsToWholeSentenceOld(benchmarkTruncateString)
   99 	}
  100 }
  101 
  102 func TestTruncateWordsToWholeSentence(t *testing.T) {
  103 	c := newTestContentSpec()
  104 	type test struct {
  105 		input, expected string
  106 		max             int
  107 		truncated       bool
  108 	}
  109 	data := []test{
  110 		{"a b c", "a b c", 12, false},
  111 		{"a b c", "a b c", 3, false},
  112 		{"a", "a", 1, false},
  113 		{"This is a sentence.", "This is a sentence.", 5, false},
  114 		{"This is also a sentence!", "This is also a sentence!", 1, false},
  115 		{"To be. Or not to be. That's the question.", "To be.", 1, true},
  116 		{" \nThis is not a sentence\nAnd this is another", "This is not a sentence", 4, true},
  117 		{"", "", 10, false},
  118 		{"This... is a more difficult test?", "This... is a more difficult test?", 1, false},
  119 	}
  120 	for i, d := range data {
  121 		c.summaryLength = d.max
  122 		output, truncated := c.TruncateWordsToWholeSentence(d.input)
  123 		if d.expected != output {
  124 			t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output)
  125 		}
  126 
  127 		if d.truncated != truncated {
  128 			t.Errorf("Test %d failed. Expected truncated=%t got %t", i, d.truncated, truncated)
  129 		}
  130 	}
  131 }
  132 
  133 func TestTruncateWordsByRune(t *testing.T) {
  134 	c := newTestContentSpec()
  135 	type test struct {
  136 		input, expected string
  137 		max             int
  138 		truncated       bool
  139 	}
  140 	data := []test{
  141 		{"", "", 1, false},
  142 		{"a b c", "a b c", 12, false},
  143 		{"a b c", "a b c", 3, false},
  144 		{"a", "a", 1, false},
  145 		{"Hello 中国", "", 0, true},
  146 		{"这是中文,全中文。", "这是中文,", 5, true},
  147 		{"Hello 中国", "Hello 中", 2, true},
  148 		{"Hello 中国", "Hello 中国", 3, false},
  149 		{"Hello中国 Good 好的", "Hello中国 Good 好", 9, true},
  150 		{"This is a sentence.", "This is", 2, true},
  151 		{"This is also a sentence!", "This", 1, true},
  152 		{"To be. Or not to be. That's the question.", "To be. Or not", 4, true},
  153 		{" \nThis is    not a sentence\n ", "This is not", 3, true},
  154 	}
  155 	for i, d := range data {
  156 		c.summaryLength = d.max
  157 		output, truncated := c.TruncateWordsByRune(strings.Fields(d.input))
  158 		if d.expected != output {
  159 			t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output)
  160 		}
  161 
  162 		if d.truncated != truncated {
  163 			t.Errorf("Test %d failed. Expected truncated=%t got %t", i, d.truncated, truncated)
  164 		}
  165 	}
  166 }
  167 
  168 func TestExtractTOCNormalContent(t *testing.T) {
  169 	content := []byte("<nav>\n<ul>\nTOC<li><a href=\"#")
  170 
  171 	actualTocLessContent, actualToc := ExtractTOC(content)
  172 	expectedTocLess := []byte("TOC<li><a href=\"#")
  173 	expectedToc := []byte("<nav id=\"TableOfContents\">\n<ul>\n")
  174 
  175 	if !bytes.Equal(actualTocLessContent, expectedTocLess) {
  176 		t.Errorf("Actual tocless (%s) did not equal expected (%s) tocless content", actualTocLessContent, expectedTocLess)
  177 	}
  178 
  179 	if !bytes.Equal(actualToc, expectedToc) {
  180 		t.Errorf("Actual toc (%s) did not equal expected (%s) toc content", actualToc, expectedToc)
  181 	}
  182 }
  183 
  184 func TestExtractTOCGreaterThanSeventy(t *testing.T) {
  185 	content := []byte("<nav>\n<ul>\nTOC This is a very long content which will definitely be greater than seventy, I promise you that.<li><a href=\"#")
  186 
  187 	actualTocLessContent, actualToc := ExtractTOC(content)
  188 	// Because the start of Toc is greater than 70+startpoint of <li> content and empty TOC will be returned
  189 	expectedToc := []byte("")
  190 
  191 	if !bytes.Equal(actualTocLessContent, content) {
  192 		t.Errorf("Actual tocless (%s) did not equal expected (%s) tocless content", actualTocLessContent, content)
  193 	}
  194 
  195 	if !bytes.Equal(actualToc, expectedToc) {
  196 		t.Errorf("Actual toc (%s) did not equal expected (%s) toc content", actualToc, expectedToc)
  197 	}
  198 }
  199 
  200 func TestExtractNoTOC(t *testing.T) {
  201 	content := []byte("TOC")
  202 
  203 	actualTocLessContent, actualToc := ExtractTOC(content)
  204 	expectedToc := []byte("")
  205 
  206 	if !bytes.Equal(actualTocLessContent, content) {
  207 		t.Errorf("Actual tocless (%s) did not equal expected (%s) tocless content", actualTocLessContent, content)
  208 	}
  209 
  210 	if !bytes.Equal(actualToc, expectedToc) {
  211 		t.Errorf("Actual toc (%s) did not equal expected (%s) toc content", actualToc, expectedToc)
  212 	}
  213 }
  214 
  215 var totalWordsBenchmarkString = strings.Repeat("Hugo Rocks ", 200)
  216 
  217 func TestTotalWords(t *testing.T) {
  218 	for i, this := range []struct {
  219 		s     string
  220 		words int
  221 	}{
  222 		{"Two, Words!", 2},
  223 		{"Word", 1},
  224 		{"", 0},
  225 		{"One, Two,      Three", 3},
  226 		{totalWordsBenchmarkString, 400},
  227 	} {
  228 		actualWordCount := TotalWords(this.s)
  229 
  230 		if actualWordCount != this.words {
  231 			t.Errorf("[%d] Actual word count (%d) for test string (%s) did not match %d", i, actualWordCount, this.s, this.words)
  232 		}
  233 	}
  234 }
  235 
  236 func BenchmarkTotalWords(b *testing.B) {
  237 	b.ResetTimer()
  238 	for i := 0; i < b.N; i++ {
  239 		wordCount := TotalWords(totalWordsBenchmarkString)
  240 		if wordCount != 400 {
  241 			b.Fatal("Wordcount error")
  242 		}
  243 	}
  244 }