github.com/gohugoio/hugo@v0.88.1/output/layout_test.go (about)

     1  // Copyright 2017-present 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 output
    15  
    16  import (
    17  	"fmt"
    18  	"reflect"
    19  	"strings"
    20  	"testing"
    21  
    22  	"github.com/gohugoio/hugo/media"
    23  
    24  	qt "github.com/frankban/quicktest"
    25  	"github.com/kylelemons/godebug/diff"
    26  )
    27  
    28  func TestLayout(t *testing.T) {
    29  	c := qt.New(t)
    30  
    31  	noExtNoDelimMediaType := media.WithDelimiterAndSuffixes(media.TextType, "", "")
    32  	noExtMediaType := media.WithDelimiterAndSuffixes(media.TextType, ".", "")
    33  
    34  	var (
    35  		ampType = Format{
    36  			Name:      "AMP",
    37  			MediaType: media.HTMLType,
    38  			BaseName:  "index",
    39  		}
    40  
    41  		htmlFormat = HTMLFormat
    42  
    43  		noExtDelimFormat = Format{
    44  			Name:      "NEM",
    45  			MediaType: noExtNoDelimMediaType,
    46  			BaseName:  "_redirects",
    47  		}
    48  
    49  		noExt = Format{
    50  			Name:      "NEX",
    51  			MediaType: noExtMediaType,
    52  			BaseName:  "next",
    53  		}
    54  	)
    55  
    56  	for _, this := range []struct {
    57  		name             string
    58  		layoutDescriptor LayoutDescriptor
    59  		layoutOverride   string
    60  		format           Format
    61  		expect           []string
    62  	}{
    63  		{
    64  			"Home",
    65  			LayoutDescriptor{Kind: "home"},
    66  			"", ampType,
    67  			[]string{
    68  				"index.amp.html",
    69  				"home.amp.html",
    70  				"list.amp.html",
    71  				"index.html",
    72  				"home.html",
    73  				"list.html",
    74  				"_default/index.amp.html",
    75  				"_default/home.amp.html",
    76  				"_default/list.amp.html",
    77  				"_default/index.html",
    78  				"_default/home.html",
    79  				"_default/list.html",
    80  			},
    81  		},
    82  		{
    83  			"Home baseof",
    84  			LayoutDescriptor{Kind: "home", Baseof: true},
    85  			"", ampType,
    86  			[]string{
    87  				"index-baseof.amp.html",
    88  				"home-baseof.amp.html",
    89  				"list-baseof.amp.html",
    90  				"baseof.amp.html",
    91  				"index-baseof.html",
    92  				"home-baseof.html",
    93  				"list-baseof.html",
    94  				"baseof.html",
    95  				"_default/index-baseof.amp.html",
    96  				"_default/home-baseof.amp.html",
    97  				"_default/list-baseof.amp.html",
    98  				"_default/baseof.amp.html",
    99  				"_default/index-baseof.html",
   100  				"_default/home-baseof.html",
   101  				"_default/list-baseof.html",
   102  				"_default/baseof.html",
   103  			},
   104  		},
   105  		{
   106  			"Home, HTML",
   107  			LayoutDescriptor{Kind: "home"},
   108  			"", htmlFormat,
   109  			// We will eventually get to index.html. This looks stuttery, but makes the lookup logic easy to understand.
   110  			[]string{
   111  				"index.html.html",
   112  				"home.html.html",
   113  				"list.html.html",
   114  				"index.html",
   115  				"home.html",
   116  				"list.html",
   117  				"_default/index.html.html",
   118  				"_default/home.html.html",
   119  				"_default/list.html.html",
   120  				"_default/index.html",
   121  				"_default/home.html",
   122  				"_default/list.html",
   123  			},
   124  		},
   125  		{
   126  			"Home, HTML, baseof",
   127  			LayoutDescriptor{Kind: "home", Baseof: true},
   128  			"", htmlFormat,
   129  			[]string{
   130  				"index-baseof.html.html",
   131  				"home-baseof.html.html",
   132  				"list-baseof.html.html",
   133  				"baseof.html.html",
   134  				"index-baseof.html",
   135  				"home-baseof.html",
   136  				"list-baseof.html",
   137  				"baseof.html",
   138  				"_default/index-baseof.html.html",
   139  				"_default/home-baseof.html.html",
   140  				"_default/list-baseof.html.html",
   141  				"_default/baseof.html.html",
   142  				"_default/index-baseof.html",
   143  				"_default/home-baseof.html",
   144  				"_default/list-baseof.html",
   145  				"_default/baseof.html",
   146  			},
   147  		},
   148  		{
   149  			"Home, french language",
   150  			LayoutDescriptor{Kind: "home", Lang: "fr"},
   151  			"", ampType,
   152  			[]string{
   153  				"index.fr.amp.html",
   154  				"home.fr.amp.html",
   155  				"list.fr.amp.html",
   156  				"index.amp.html",
   157  				"home.amp.html",
   158  				"list.amp.html",
   159  				"index.fr.html",
   160  				"home.fr.html",
   161  				"list.fr.html",
   162  				"index.html",
   163  				"home.html",
   164  				"list.html",
   165  				"_default/index.fr.amp.html",
   166  				"_default/home.fr.amp.html",
   167  				"_default/list.fr.amp.html",
   168  				"_default/index.amp.html",
   169  				"_default/home.amp.html",
   170  				"_default/list.amp.html",
   171  				"_default/index.fr.html",
   172  				"_default/home.fr.html",
   173  				"_default/list.fr.html",
   174  				"_default/index.html",
   175  				"_default/home.html",
   176  				"_default/list.html",
   177  			},
   178  		},
   179  		{
   180  			"Home, no ext or delim",
   181  			LayoutDescriptor{Kind: "home"},
   182  			"", noExtDelimFormat,
   183  			[]string{
   184  				"index.nem",
   185  				"home.nem",
   186  				"list.nem",
   187  				"_default/index.nem",
   188  				"_default/home.nem",
   189  				"_default/list.nem",
   190  			},
   191  		},
   192  		{
   193  			"Home, no ext",
   194  			LayoutDescriptor{Kind: "home"},
   195  			"", noExt,
   196  			[]string{
   197  				"index.nex",
   198  				"home.nex",
   199  				"list.nex",
   200  				"_default/index.nex",
   201  				"_default/home.nex",
   202  				"_default/list.nex",
   203  			},
   204  		},
   205  		{
   206  			"Page, no ext or delim",
   207  			LayoutDescriptor{Kind: "page"},
   208  			"", noExtDelimFormat,
   209  			[]string{"_default/single.nem"},
   210  		},
   211  		{
   212  			"Section",
   213  			LayoutDescriptor{Kind: "section", Section: "sect1"},
   214  			"", ampType,
   215  			[]string{
   216  				"sect1/sect1.amp.html",
   217  				"sect1/section.amp.html",
   218  				"sect1/list.amp.html",
   219  				"sect1/sect1.html",
   220  				"sect1/section.html",
   221  				"sect1/list.html",
   222  				"section/sect1.amp.html",
   223  				"section/section.amp.html",
   224  				"section/list.amp.html",
   225  				"section/sect1.html",
   226  				"section/section.html",
   227  				"section/list.html",
   228  				"_default/sect1.amp.html",
   229  				"_default/section.amp.html",
   230  				"_default/list.amp.html",
   231  				"_default/sect1.html",
   232  				"_default/section.html",
   233  				"_default/list.html",
   234  			},
   235  		},
   236  		{
   237  			"Section, baseof",
   238  			LayoutDescriptor{Kind: "section", Section: "sect1", Baseof: true},
   239  			"", ampType,
   240  			[]string{
   241  				"sect1/sect1-baseof.amp.html",
   242  				"sect1/section-baseof.amp.html",
   243  				"sect1/list-baseof.amp.html",
   244  				"sect1/baseof.amp.html",
   245  				"sect1/sect1-baseof.html",
   246  				"sect1/section-baseof.html",
   247  				"sect1/list-baseof.html",
   248  				"sect1/baseof.html",
   249  				"section/sect1-baseof.amp.html",
   250  				"section/section-baseof.amp.html",
   251  				"section/list-baseof.amp.html",
   252  				"section/baseof.amp.html",
   253  				"section/sect1-baseof.html",
   254  				"section/section-baseof.html",
   255  				"section/list-baseof.html",
   256  				"section/baseof.html",
   257  				"_default/sect1-baseof.amp.html",
   258  				"_default/section-baseof.amp.html",
   259  				"_default/list-baseof.amp.html",
   260  				"_default/baseof.amp.html",
   261  				"_default/sect1-baseof.html",
   262  				"_default/section-baseof.html",
   263  				"_default/list-baseof.html",
   264  				"_default/baseof.html",
   265  			},
   266  		},
   267  		{
   268  			"Section, baseof, French, AMP",
   269  			LayoutDescriptor{Kind: "section", Section: "sect1", Lang: "fr", Baseof: true},
   270  			"", ampType,
   271  			[]string{
   272  				"sect1/sect1-baseof.fr.amp.html",
   273  				"sect1/section-baseof.fr.amp.html",
   274  				"sect1/list-baseof.fr.amp.html",
   275  				"sect1/baseof.fr.amp.html",
   276  				"sect1/sect1-baseof.amp.html",
   277  				"sect1/section-baseof.amp.html",
   278  				"sect1/list-baseof.amp.html",
   279  				"sect1/baseof.amp.html",
   280  				"sect1/sect1-baseof.fr.html",
   281  				"sect1/section-baseof.fr.html",
   282  				"sect1/list-baseof.fr.html",
   283  				"sect1/baseof.fr.html",
   284  				"sect1/sect1-baseof.html",
   285  				"sect1/section-baseof.html",
   286  				"sect1/list-baseof.html",
   287  				"sect1/baseof.html",
   288  				"section/sect1-baseof.fr.amp.html",
   289  				"section/section-baseof.fr.amp.html",
   290  				"section/list-baseof.fr.amp.html",
   291  				"section/baseof.fr.amp.html",
   292  				"section/sect1-baseof.amp.html",
   293  				"section/section-baseof.amp.html",
   294  				"section/list-baseof.amp.html",
   295  				"section/baseof.amp.html",
   296  				"section/sect1-baseof.fr.html",
   297  				"section/section-baseof.fr.html",
   298  				"section/list-baseof.fr.html",
   299  				"section/baseof.fr.html",
   300  				"section/sect1-baseof.html",
   301  				"section/section-baseof.html",
   302  				"section/list-baseof.html",
   303  				"section/baseof.html",
   304  				"_default/sect1-baseof.fr.amp.html",
   305  				"_default/section-baseof.fr.amp.html",
   306  				"_default/list-baseof.fr.amp.html",
   307  				"_default/baseof.fr.amp.html",
   308  				"_default/sect1-baseof.amp.html",
   309  				"_default/section-baseof.amp.html",
   310  				"_default/list-baseof.amp.html",
   311  				"_default/baseof.amp.html",
   312  				"_default/sect1-baseof.fr.html",
   313  				"_default/section-baseof.fr.html",
   314  				"_default/list-baseof.fr.html",
   315  				"_default/baseof.fr.html",
   316  				"_default/sect1-baseof.html",
   317  				"_default/section-baseof.html",
   318  				"_default/list-baseof.html",
   319  				"_default/baseof.html",
   320  			},
   321  		},
   322  		{
   323  			"Section with layout",
   324  			LayoutDescriptor{Kind: "section", Section: "sect1", Layout: "mylayout"},
   325  			"", ampType,
   326  			[]string{
   327  				"sect1/mylayout.amp.html",
   328  				"sect1/sect1.amp.html",
   329  				"sect1/section.amp.html",
   330  				"sect1/list.amp.html",
   331  				"sect1/mylayout.html",
   332  				"sect1/sect1.html",
   333  				"sect1/section.html",
   334  				"sect1/list.html",
   335  				"section/mylayout.amp.html",
   336  				"section/sect1.amp.html",
   337  				"section/section.amp.html",
   338  				"section/list.amp.html",
   339  				"section/mylayout.html",
   340  				"section/sect1.html",
   341  				"section/section.html",
   342  				"section/list.html",
   343  				"_default/mylayout.amp.html",
   344  				"_default/sect1.amp.html",
   345  				"_default/section.amp.html",
   346  				"_default/list.amp.html",
   347  				"_default/mylayout.html",
   348  				"_default/sect1.html",
   349  				"_default/section.html",
   350  				"_default/list.html",
   351  			},
   352  		},
   353  		{
   354  			"Term, French, AMP",
   355  			LayoutDescriptor{Kind: "term", Section: "tags", Lang: "fr"},
   356  			"", ampType,
   357  			[]string{
   358  				"term/term.fr.amp.html",
   359  				"term/tags.fr.amp.html",
   360  				"term/taxonomy.fr.amp.html",
   361  				"term/list.fr.amp.html",
   362  				"term/term.amp.html",
   363  				"term/tags.amp.html",
   364  				"term/taxonomy.amp.html",
   365  				"term/list.amp.html",
   366  				"term/term.fr.html",
   367  				"term/tags.fr.html",
   368  				"term/taxonomy.fr.html",
   369  				"term/list.fr.html",
   370  				"term/term.html",
   371  				"term/tags.html",
   372  				"term/taxonomy.html",
   373  				"term/list.html",
   374  				"taxonomy/term.fr.amp.html",
   375  				"taxonomy/tags.fr.amp.html",
   376  				"taxonomy/taxonomy.fr.amp.html",
   377  				"taxonomy/list.fr.amp.html",
   378  				"taxonomy/term.amp.html",
   379  				"taxonomy/tags.amp.html",
   380  				"taxonomy/taxonomy.amp.html",
   381  				"taxonomy/list.amp.html",
   382  				"taxonomy/term.fr.html",
   383  				"taxonomy/tags.fr.html",
   384  				"taxonomy/taxonomy.fr.html",
   385  				"taxonomy/list.fr.html",
   386  				"taxonomy/term.html",
   387  				"taxonomy/tags.html",
   388  				"taxonomy/taxonomy.html",
   389  				"taxonomy/list.html",
   390  				"tags/term.fr.amp.html",
   391  				"tags/tags.fr.amp.html",
   392  				"tags/taxonomy.fr.amp.html",
   393  				"tags/list.fr.amp.html",
   394  				"tags/term.amp.html",
   395  				"tags/tags.amp.html",
   396  				"tags/taxonomy.amp.html",
   397  				"tags/list.amp.html",
   398  				"tags/term.fr.html",
   399  				"tags/tags.fr.html",
   400  				"tags/taxonomy.fr.html",
   401  				"tags/list.fr.html",
   402  				"tags/term.html",
   403  				"tags/tags.html",
   404  				"tags/taxonomy.html",
   405  				"tags/list.html",
   406  				"_default/term.fr.amp.html",
   407  				"_default/tags.fr.amp.html",
   408  				"_default/taxonomy.fr.amp.html",
   409  				"_default/list.fr.amp.html",
   410  				"_default/term.amp.html",
   411  				"_default/tags.amp.html",
   412  				"_default/taxonomy.amp.html",
   413  				"_default/list.amp.html",
   414  				"_default/term.fr.html",
   415  				"_default/tags.fr.html",
   416  				"_default/taxonomy.fr.html",
   417  				"_default/list.fr.html",
   418  				"_default/term.html",
   419  				"_default/tags.html",
   420  				"_default/taxonomy.html",
   421  				"_default/list.html",
   422  			},
   423  		},
   424  		{
   425  			"Term, baseof, French, AMP",
   426  			LayoutDescriptor{Kind: "term", Section: "tags", Lang: "fr", Baseof: true},
   427  			"", ampType,
   428  			[]string{
   429  				"term/term-baseof.fr.amp.html",
   430  				"term/tags-baseof.fr.amp.html",
   431  				"term/taxonomy-baseof.fr.amp.html",
   432  				"term/list-baseof.fr.amp.html",
   433  				"term/baseof.fr.amp.html",
   434  				"term/term-baseof.amp.html",
   435  				"term/tags-baseof.amp.html",
   436  				"term/taxonomy-baseof.amp.html",
   437  				"term/list-baseof.amp.html",
   438  				"term/baseof.amp.html",
   439  				"term/term-baseof.fr.html",
   440  				"term/tags-baseof.fr.html",
   441  				"term/taxonomy-baseof.fr.html",
   442  				"term/list-baseof.fr.html",
   443  				"term/baseof.fr.html",
   444  				"term/term-baseof.html",
   445  				"term/tags-baseof.html",
   446  				"term/taxonomy-baseof.html",
   447  				"term/list-baseof.html",
   448  				"term/baseof.html",
   449  				"taxonomy/term-baseof.fr.amp.html",
   450  				"taxonomy/tags-baseof.fr.amp.html",
   451  				"taxonomy/taxonomy-baseof.fr.amp.html",
   452  				"taxonomy/list-baseof.fr.amp.html",
   453  				"taxonomy/baseof.fr.amp.html",
   454  				"taxonomy/term-baseof.amp.html",
   455  				"taxonomy/tags-baseof.amp.html",
   456  				"taxonomy/taxonomy-baseof.amp.html",
   457  				"taxonomy/list-baseof.amp.html",
   458  				"taxonomy/baseof.amp.html",
   459  				"taxonomy/term-baseof.fr.html",
   460  				"taxonomy/tags-baseof.fr.html",
   461  				"taxonomy/taxonomy-baseof.fr.html",
   462  				"taxonomy/list-baseof.fr.html",
   463  				"taxonomy/baseof.fr.html",
   464  				"taxonomy/term-baseof.html",
   465  				"taxonomy/tags-baseof.html",
   466  				"taxonomy/taxonomy-baseof.html",
   467  				"taxonomy/list-baseof.html",
   468  				"taxonomy/baseof.html",
   469  				"tags/term-baseof.fr.amp.html",
   470  				"tags/tags-baseof.fr.amp.html",
   471  				"tags/taxonomy-baseof.fr.amp.html",
   472  				"tags/list-baseof.fr.amp.html",
   473  				"tags/baseof.fr.amp.html",
   474  				"tags/term-baseof.amp.html",
   475  				"tags/tags-baseof.amp.html",
   476  				"tags/taxonomy-baseof.amp.html",
   477  				"tags/list-baseof.amp.html",
   478  				"tags/baseof.amp.html",
   479  				"tags/term-baseof.fr.html",
   480  				"tags/tags-baseof.fr.html",
   481  				"tags/taxonomy-baseof.fr.html",
   482  				"tags/list-baseof.fr.html",
   483  				"tags/baseof.fr.html",
   484  				"tags/term-baseof.html",
   485  				"tags/tags-baseof.html",
   486  				"tags/taxonomy-baseof.html",
   487  				"tags/list-baseof.html",
   488  				"tags/baseof.html",
   489  				"_default/term-baseof.fr.amp.html",
   490  				"_default/tags-baseof.fr.amp.html",
   491  				"_default/taxonomy-baseof.fr.amp.html",
   492  				"_default/list-baseof.fr.amp.html",
   493  				"_default/baseof.fr.amp.html",
   494  				"_default/term-baseof.amp.html",
   495  				"_default/tags-baseof.amp.html",
   496  				"_default/taxonomy-baseof.amp.html",
   497  				"_default/list-baseof.amp.html",
   498  				"_default/baseof.amp.html",
   499  				"_default/term-baseof.fr.html",
   500  				"_default/tags-baseof.fr.html",
   501  				"_default/taxonomy-baseof.fr.html",
   502  				"_default/list-baseof.fr.html",
   503  				"_default/baseof.fr.html",
   504  				"_default/term-baseof.html",
   505  				"_default/tags-baseof.html",
   506  				"_default/taxonomy-baseof.html",
   507  				"_default/list-baseof.html",
   508  				"_default/baseof.html",
   509  			},
   510  		},
   511  		{
   512  			"Term",
   513  			LayoutDescriptor{Kind: "term", Section: "tags"},
   514  			"", ampType,
   515  			[]string{
   516  				"term/term.amp.html",
   517  				"term/tags.amp.html",
   518  				"term/taxonomy.amp.html",
   519  				"term/list.amp.html",
   520  				"term/term.html",
   521  				"term/tags.html",
   522  				"term/taxonomy.html",
   523  				"term/list.html",
   524  				"taxonomy/term.amp.html",
   525  				"taxonomy/tags.amp.html",
   526  				"taxonomy/taxonomy.amp.html",
   527  				"taxonomy/list.amp.html",
   528  				"taxonomy/term.html",
   529  				"taxonomy/tags.html",
   530  				"taxonomy/taxonomy.html",
   531  				"taxonomy/list.html",
   532  				"tags/term.amp.html",
   533  				"tags/tags.amp.html",
   534  				"tags/taxonomy.amp.html",
   535  				"tags/list.amp.html",
   536  				"tags/term.html",
   537  				"tags/tags.html",
   538  				"tags/taxonomy.html",
   539  				"tags/list.html",
   540  				"_default/term.amp.html",
   541  				"_default/tags.amp.html",
   542  				"_default/taxonomy.amp.html",
   543  				"_default/list.amp.html",
   544  				"_default/term.html",
   545  				"_default/tags.html",
   546  				"_default/taxonomy.html",
   547  				"_default/list.html",
   548  			},
   549  		},
   550  		{
   551  			"Taxonomy",
   552  			LayoutDescriptor{Kind: "taxonomy", Section: "categories"},
   553  			"", ampType,
   554  			[]string{
   555  				"categories/categories.terms.amp.html",
   556  				"categories/terms.amp.html",
   557  				"categories/taxonomy.amp.html",
   558  				"categories/list.amp.html",
   559  				"categories/categories.terms.html",
   560  				"categories/terms.html",
   561  				"categories/taxonomy.html",
   562  				"categories/list.html",
   563  				"taxonomy/categories.terms.amp.html",
   564  				"taxonomy/terms.amp.html",
   565  				"taxonomy/taxonomy.amp.html",
   566  				"taxonomy/list.amp.html",
   567  				"taxonomy/categories.terms.html",
   568  				"taxonomy/terms.html",
   569  				"taxonomy/taxonomy.html",
   570  				"taxonomy/list.html",
   571  				"_default/categories.terms.amp.html",
   572  				"_default/terms.amp.html",
   573  				"_default/taxonomy.amp.html",
   574  				"_default/list.amp.html",
   575  				"_default/categories.terms.html",
   576  				"_default/terms.html",
   577  				"_default/taxonomy.html",
   578  				"_default/list.html",
   579  			},
   580  		},
   581  		{
   582  			"Page",
   583  			LayoutDescriptor{Kind: "page"},
   584  			"", ampType,
   585  			[]string{
   586  				"_default/single.amp.html",
   587  				"_default/single.html",
   588  			},
   589  		},
   590  		{
   591  			"Page, baseof",
   592  			LayoutDescriptor{Kind: "page", Baseof: true},
   593  			"", ampType,
   594  			[]string{
   595  				"_default/single-baseof.amp.html",
   596  				"_default/baseof.amp.html",
   597  				"_default/single-baseof.html",
   598  				"_default/baseof.html",
   599  			},
   600  		},
   601  		{
   602  			"Page with layout",
   603  			LayoutDescriptor{Kind: "page", Layout: "mylayout"},
   604  			"", ampType,
   605  			[]string{
   606  				"_default/mylayout.amp.html",
   607  				"_default/single.amp.html",
   608  				"_default/mylayout.html",
   609  				"_default/single.html",
   610  			},
   611  		},
   612  		{
   613  			"Page with layout, baseof",
   614  			LayoutDescriptor{Kind: "page", Layout: "mylayout", Baseof: true},
   615  			"", ampType,
   616  			[]string{
   617  				"_default/mylayout-baseof.amp.html",
   618  				"_default/single-baseof.amp.html",
   619  				"_default/baseof.amp.html",
   620  				"_default/mylayout-baseof.html",
   621  				"_default/single-baseof.html",
   622  				"_default/baseof.html",
   623  			},
   624  		},
   625  		{
   626  			"Page with layout and type",
   627  			LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype"},
   628  			"", ampType,
   629  			[]string{
   630  				"myttype/mylayout.amp.html",
   631  				"myttype/single.amp.html",
   632  				"myttype/mylayout.html",
   633  				"myttype/single.html",
   634  				"_default/mylayout.amp.html",
   635  				"_default/single.amp.html",
   636  				"_default/mylayout.html",
   637  				"_default/single.html",
   638  			},
   639  		},
   640  		{
   641  			"Page baseof with layout and type",
   642  			LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype", Baseof: true},
   643  			"", ampType,
   644  			[]string{
   645  				"myttype/mylayout-baseof.amp.html",
   646  				"myttype/single-baseof.amp.html",
   647  				"myttype/baseof.amp.html",
   648  				"myttype/mylayout-baseof.html",
   649  				"myttype/single-baseof.html",
   650  				"myttype/baseof.html",
   651  				"_default/mylayout-baseof.amp.html",
   652  				"_default/single-baseof.amp.html",
   653  				"_default/baseof.amp.html",
   654  				"_default/mylayout-baseof.html",
   655  				"_default/single-baseof.html",
   656  				"_default/baseof.html",
   657  			},
   658  		},
   659  		{
   660  			"Page baseof with layout and type in French",
   661  			LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype", Lang: "fr", Baseof: true},
   662  			"", ampType,
   663  			[]string{
   664  				"myttype/mylayout-baseof.fr.amp.html",
   665  				"myttype/single-baseof.fr.amp.html",
   666  				"myttype/baseof.fr.amp.html",
   667  				"myttype/mylayout-baseof.amp.html",
   668  				"myttype/single-baseof.amp.html",
   669  				"myttype/baseof.amp.html",
   670  				"myttype/mylayout-baseof.fr.html",
   671  				"myttype/single-baseof.fr.html",
   672  				"myttype/baseof.fr.html",
   673  				"myttype/mylayout-baseof.html",
   674  				"myttype/single-baseof.html",
   675  				"myttype/baseof.html",
   676  				"_default/mylayout-baseof.fr.amp.html",
   677  				"_default/single-baseof.fr.amp.html",
   678  				"_default/baseof.fr.amp.html",
   679  				"_default/mylayout-baseof.amp.html",
   680  				"_default/single-baseof.amp.html",
   681  				"_default/baseof.amp.html",
   682  				"_default/mylayout-baseof.fr.html",
   683  				"_default/single-baseof.fr.html",
   684  				"_default/baseof.fr.html",
   685  				"_default/mylayout-baseof.html",
   686  				"_default/single-baseof.html",
   687  				"_default/baseof.html",
   688  			},
   689  		},
   690  		{
   691  			"Page with layout and type with subtype",
   692  			LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype/mysubtype"},
   693  			"", ampType,
   694  			[]string{
   695  				"myttype/mysubtype/mylayout.amp.html",
   696  				"myttype/mysubtype/single.amp.html",
   697  				"myttype/mysubtype/mylayout.html",
   698  				"myttype/mysubtype/single.html",
   699  				"_default/mylayout.amp.html",
   700  				"_default/single.amp.html",
   701  				"_default/mylayout.html",
   702  				"_default/single.html",
   703  			},
   704  		},
   705  		// RSS
   706  		{
   707  			"RSS Home",
   708  			LayoutDescriptor{Kind: "home"},
   709  			"", RSSFormat,
   710  			[]string{
   711  				"index.rss.xml",
   712  				"home.rss.xml",
   713  				"rss.xml",
   714  				"list.rss.xml",
   715  				"index.xml",
   716  				"home.xml",
   717  				"list.xml",
   718  				"_default/index.rss.xml",
   719  				"_default/home.rss.xml",
   720  				"_default/rss.xml",
   721  				"_default/list.rss.xml",
   722  				"_default/index.xml",
   723  				"_default/home.xml",
   724  				"_default/list.xml",
   725  				"_internal/_default/rss.xml",
   726  			},
   727  		},
   728  		{
   729  			"RSS Home, baseof",
   730  			LayoutDescriptor{Kind: "home", Baseof: true},
   731  			"", RSSFormat,
   732  			[]string{
   733  				"index-baseof.rss.xml",
   734  				"home-baseof.rss.xml",
   735  				"list-baseof.rss.xml",
   736  				"baseof.rss.xml",
   737  				"index-baseof.xml",
   738  				"home-baseof.xml",
   739  				"list-baseof.xml",
   740  				"baseof.xml",
   741  				"_default/index-baseof.rss.xml",
   742  				"_default/home-baseof.rss.xml",
   743  				"_default/list-baseof.rss.xml",
   744  				"_default/baseof.rss.xml",
   745  				"_default/index-baseof.xml",
   746  				"_default/home-baseof.xml",
   747  				"_default/list-baseof.xml",
   748  				"_default/baseof.xml",
   749  			},
   750  		},
   751  		{
   752  			"RSS Section",
   753  			LayoutDescriptor{Kind: "section", Section: "sect1"},
   754  			"", RSSFormat,
   755  			[]string{
   756  				"sect1/sect1.rss.xml",
   757  				"sect1/section.rss.xml",
   758  				"sect1/rss.xml",
   759  				"sect1/list.rss.xml",
   760  				"sect1/sect1.xml",
   761  				"sect1/section.xml",
   762  				"sect1/list.xml",
   763  				"section/sect1.rss.xml",
   764  				"section/section.rss.xml",
   765  				"section/rss.xml",
   766  				"section/list.rss.xml",
   767  				"section/sect1.xml",
   768  				"section/section.xml",
   769  				"section/list.xml",
   770  				"_default/sect1.rss.xml",
   771  				"_default/section.rss.xml",
   772  				"_default/rss.xml",
   773  				"_default/list.rss.xml",
   774  				"_default/sect1.xml",
   775  				"_default/section.xml",
   776  				"_default/list.xml",
   777  				"_internal/_default/rss.xml",
   778  			},
   779  		},
   780  		{
   781  			"RSS Term",
   782  			LayoutDescriptor{Kind: "term", Section: "tag"},
   783  			"", RSSFormat,
   784  			[]string{
   785  				"term/term.rss.xml",
   786  				"term/tag.rss.xml",
   787  				"term/taxonomy.rss.xml",
   788  				"term/rss.xml",
   789  				"term/list.rss.xml",
   790  				"term/term.xml",
   791  				"term/tag.xml",
   792  				"term/taxonomy.xml",
   793  				"term/list.xml",
   794  				"taxonomy/term.rss.xml",
   795  				"taxonomy/tag.rss.xml",
   796  				"taxonomy/taxonomy.rss.xml",
   797  				"taxonomy/rss.xml",
   798  				"taxonomy/list.rss.xml",
   799  				"taxonomy/term.xml",
   800  				"taxonomy/tag.xml",
   801  				"taxonomy/taxonomy.xml",
   802  				"taxonomy/list.xml",
   803  				"tag/term.rss.xml",
   804  				"tag/tag.rss.xml",
   805  				"tag/taxonomy.rss.xml",
   806  				"tag/rss.xml",
   807  				"tag/list.rss.xml",
   808  				"tag/term.xml",
   809  				"tag/tag.xml",
   810  				"tag/taxonomy.xml",
   811  				"tag/list.xml",
   812  				"_default/term.rss.xml",
   813  				"_default/tag.rss.xml",
   814  				"_default/taxonomy.rss.xml",
   815  				"_default/rss.xml",
   816  				"_default/list.rss.xml",
   817  				"_default/term.xml",
   818  				"_default/tag.xml",
   819  				"_default/taxonomy.xml",
   820  				"_default/list.xml",
   821  				"_internal/_default/rss.xml",
   822  			},
   823  		},
   824  		{
   825  			"RSS Taxonomy",
   826  			LayoutDescriptor{Kind: "taxonomy", Section: "tag"},
   827  			"", RSSFormat,
   828  			[]string{
   829  				"tag/tag.terms.rss.xml",
   830  				"tag/terms.rss.xml",
   831  				"tag/taxonomy.rss.xml",
   832  				"tag/rss.xml",
   833  				"tag/list.rss.xml",
   834  				"tag/tag.terms.xml",
   835  				"tag/terms.xml",
   836  				"tag/taxonomy.xml",
   837  				"tag/list.xml",
   838  				"taxonomy/tag.terms.rss.xml",
   839  				"taxonomy/terms.rss.xml",
   840  				"taxonomy/taxonomy.rss.xml",
   841  				"taxonomy/rss.xml",
   842  				"taxonomy/list.rss.xml",
   843  				"taxonomy/tag.terms.xml",
   844  				"taxonomy/terms.xml",
   845  				"taxonomy/taxonomy.xml",
   846  				"taxonomy/list.xml",
   847  				"_default/tag.terms.rss.xml",
   848  				"_default/terms.rss.xml",
   849  				"_default/taxonomy.rss.xml",
   850  				"_default/rss.xml",
   851  				"_default/list.rss.xml",
   852  				"_default/tag.terms.xml",
   853  				"_default/terms.xml",
   854  				"_default/taxonomy.xml",
   855  				"_default/list.xml",
   856  				"_internal/_default/rss.xml",
   857  			},
   858  		},
   859  		{
   860  			"Home plain text",
   861  			LayoutDescriptor{Kind: "home"},
   862  			"", JSONFormat,
   863  			[]string{
   864  				"index.json.json",
   865  				"home.json.json",
   866  				"list.json.json",
   867  				"index.json",
   868  				"home.json",
   869  				"list.json",
   870  				"_default/index.json.json",
   871  				"_default/home.json.json",
   872  				"_default/list.json.json",
   873  				"_default/index.json",
   874  				"_default/home.json",
   875  				"_default/list.json",
   876  			},
   877  		},
   878  		{
   879  			"Page plain text",
   880  			LayoutDescriptor{Kind: "page"},
   881  			"", JSONFormat,
   882  			[]string{
   883  				"_default/single.json.json",
   884  				"_default/single.json",
   885  			},
   886  		},
   887  		{
   888  			"Reserved section, shortcodes",
   889  			LayoutDescriptor{Kind: "section", Section: "shortcodes", Type: "shortcodes"},
   890  			"", ampType,
   891  			[]string{
   892  				"section/shortcodes.amp.html",
   893  				"section/section.amp.html",
   894  				"section/list.amp.html",
   895  				"section/shortcodes.html",
   896  				"section/section.html",
   897  				"section/list.html",
   898  				"_default/shortcodes.amp.html",
   899  				"_default/section.amp.html",
   900  				"_default/list.amp.html",
   901  				"_default/shortcodes.html",
   902  				"_default/section.html",
   903  				"_default/list.html",
   904  			},
   905  		},
   906  		{
   907  			"Reserved section, partials",
   908  			LayoutDescriptor{Kind: "section", Section: "partials", Type: "partials"},
   909  			"", ampType,
   910  			[]string{
   911  				"section/partials.amp.html",
   912  				"section/section.amp.html",
   913  				"section/list.amp.html",
   914  				"section/partials.html",
   915  				"section/section.html",
   916  				"section/list.html",
   917  				"_default/partials.amp.html",
   918  				"_default/section.amp.html",
   919  				"_default/list.amp.html",
   920  				"_default/partials.html",
   921  				"_default/section.html",
   922  				"_default/list.html",
   923  			},
   924  		},
   925  		// This is currently always HTML only
   926  		{
   927  			"404, HTML",
   928  			LayoutDescriptor{Kind: "404"},
   929  			"", htmlFormat,
   930  			[]string{
   931  				"404.html.html",
   932  				"404.html",
   933  			},
   934  		},
   935  		{
   936  			"404, HTML baseof",
   937  			LayoutDescriptor{Kind: "404", Baseof: true},
   938  			"", htmlFormat,
   939  			[]string{
   940  				"404-baseof.html.html",
   941  				"baseof.html.html",
   942  				"404-baseof.html",
   943  				"baseof.html",
   944  				"_default/404-baseof.html.html",
   945  				"_default/baseof.html.html",
   946  				"_default/404-baseof.html",
   947  				"_default/baseof.html",
   948  			},
   949  		},
   950  		{
   951  			"Content hook",
   952  			LayoutDescriptor{Kind: "render-link", RenderingHook: true, Layout: "mylayout", Section: "blog"},
   953  			"", ampType,
   954  			[]string{
   955  				"blog/_markup/render-link.amp.html",
   956  				"blog/_markup/render-link.html",
   957  				"_default/_markup/render-link.amp.html",
   958  				"_default/_markup/render-link.html",
   959  			},
   960  		},
   961  	} {
   962  		c.Run(this.name, func(c *qt.C) {
   963  			l := NewLayoutHandler()
   964  
   965  			layouts, err := l.For(this.layoutDescriptor, this.format)
   966  
   967  			c.Assert(err, qt.IsNil)
   968  			c.Assert(layouts, qt.Not(qt.IsNil), qt.Commentf(this.layoutDescriptor.Kind))
   969  
   970  			if !reflect.DeepEqual(layouts, this.expect) {
   971  				r := strings.NewReplacer(
   972  					"[", "\t\"",
   973  					"]", "\",",
   974  					" ", "\",\n\t\"",
   975  				)
   976  				fmtGot := r.Replace(fmt.Sprintf("%v", layouts))
   977  				fmtExp := r.Replace(fmt.Sprintf("%v", this.expect))
   978  
   979  				c.Fatalf("got %d items, expected %d:\nGot:\n\t%v\nExpected:\n\t%v\nDiff:\n%s", len(layouts), len(this.expect), layouts, this.expect, diff.Diff(fmtExp, fmtGot))
   980  
   981  			}
   982  		})
   983  	}
   984  }
   985  
   986  func BenchmarkLayout(b *testing.B) {
   987  	descriptor := LayoutDescriptor{Kind: "taxonomy", Section: "categories"}
   988  	l := NewLayoutHandler()
   989  
   990  	for i := 0; i < b.N; i++ {
   991  		_, err := l.For(descriptor, HTMLFormat)
   992  		if err != nil {
   993  			panic(err)
   994  		}
   995  	}
   996  }
   997  
   998  func BenchmarkLayoutUncached(b *testing.B) {
   999  	for i := 0; i < b.N; i++ {
  1000  		descriptor := LayoutDescriptor{Kind: "taxonomy", Section: "categories"}
  1001  		l := NewLayoutHandler()
  1002  
  1003  		_, err := l.For(descriptor, HTMLFormat)
  1004  		if err != nil {
  1005  			panic(err)
  1006  		}
  1007  	}
  1008  }