diff --git a/templates/template.go b/templates/template.go index 6cd1e9ac..6b4536e1 100644 --- a/templates/template.go +++ b/templates/template.go @@ -40,6 +40,8 @@ func init() { fmt.Println("Template Live Update enabled") } } + +// Commonvariables return a jet.VarMap variable containing the necessary variables to run index layouts func Commonvariables(c *gin.Context) jet.VarMap { token := nosurf.Token(c.Request) msg := messages.GetMessages(c) @@ -60,7 +62,7 @@ func Commonvariables(c *gin.Context) jet.VarMap { return variables } -// newPanelSearchForm : Helper that creates a search form without items/page field +// NewPanelSearchForm : Helper that creates a search form without items/page field // these need to be used when the templateVariables don't include `navigation` func NewPanelSearchForm(c *gin.Context) SearchForm { form := NewSearchForm(c) @@ -68,13 +70,14 @@ func NewPanelSearchForm(c *gin.Context) SearchForm { return form } -// +// NewPanelCommonvariables return a jet.VarMap variable containing the necessary variables to run index admin layouts func NewPanelCommonvariables(c *gin.Context) jet.VarMap { common := Commonvariables(c) common.Set("Search", NewPanelSearchForm(c)) return common } +// Render is a function rendering a template func Render(c *gin.Context, templateName string, variables jet.VarMap) { t, err := View.GetTemplate(templateName) if err != nil { @@ -87,6 +90,7 @@ func Render(c *gin.Context, templateName string, variables jet.VarMap) { } } +// HttpError render an error template func HttpError(c *gin.Context, errorCode int) { switch errorCode { case http.StatusNotFound: @@ -104,6 +108,7 @@ func HttpError(c *gin.Context, errorCode int) { } } +// Static render static templates func Static(c *gin.Context, templateName string) { var variables jet.VarMap if isAdminTemplate(templateName) { @@ -114,6 +119,7 @@ func Static(c *gin.Context, templateName string) { Render(c, templateName, variables) } +// ModelList render list models templates func ModelList(c *gin.Context, templateName string, models interface{}, nav Navigation, search SearchForm) { var variables jet.VarMap if isAdminTemplate(templateName) { @@ -127,6 +133,7 @@ func ModelList(c *gin.Context, templateName string, models interface{}, nav Navi Render(c, templateName, variables) } +// Form render a template form func Form(c *gin.Context, templateName string, form interface{}) { var variables jet.VarMap if isAdminTemplate(templateName) { @@ -138,6 +145,7 @@ func Form(c *gin.Context, templateName string, form interface{}) { Render(c, templateName, variables) } +// Torrent render a torrent view template func Torrent(c *gin.Context, torrent models.TorrentJSON, rootFolder *filelist.FileListFolder, captchaID string) { variables := Commonvariables(c) variables.Set("Torrent", torrent) @@ -146,6 +154,7 @@ func Torrent(c *gin.Context, torrent models.TorrentJSON, rootFolder *filelist.Fi Render(c, path.Join(SiteDir, "torrents/view.jet.html"), variables) } +// UserProfileEdit render a form to edit a profile func UserProfileEdit(c *gin.Context, userProfile *models.User, userForm userValidator.UserForm, languages publicSettings.Languages) { variables := Commonvariables(c) variables.Set("UserProfile", userProfile) @@ -154,23 +163,29 @@ func UserProfileEdit(c *gin.Context, userProfile *models.User, userForm userVali Render(c, path.Join(SiteDir, "user/edit.jet.html"), variables) } +// UserProfile render a user profile func UserProfile(c *gin.Context, userProfile *models.User) { variables := Commonvariables(c) variables.Set("UserProfile", userProfile) Render(c, path.Join(SiteDir, "user/torrents.jet.html"), variables) } +// UserProfileNotifications render a user profile notifications func UserProfileNotifications(c *gin.Context, userProfile *models.User) { variables := Commonvariables(c) variables.Set("UserProfile", userProfile) Render(c, path.Join(SiteDir, "user/notifications.jet.html"), variables) } + +// DatabaseDump render the list of database dumps template func DatabaseDump(c *gin.Context, listDumps []models.DatabaseDumpJSON, GPGLink string) { variables := Commonvariables(c) variables.Set("ListDumps", listDumps) variables.Set("GPGLink", GPGLink) Render(c, path.Join(SiteDir, "database/dumps.jet.html"), variables) } + +// PanelAdmin render the panel admin template index func PanelAdmin(c *gin.Context, torrent []models.Torrent, reports []models.TorrentReportJSON, users []models.User, comments []models.Comment) { variables := NewPanelCommonvariables(c) variables.Set("Torrents", torrent) diff --git a/templates/template_functions.go b/templates/template_functions.go index a380c325..d7aff079 100644 --- a/templates/template_functions.go +++ b/templates/template_functions.go @@ -20,280 +20,276 @@ import ( "github.com/NyaaPantsu/nyaa/utils/torrentLanguages" ) -type captchaData struct { - CaptchaID string - T publicSettings.TemplateTfunc -} - // FuncMap : Functions accessible in templates by {{ $.Function }} func templateFunctions(vars jet.VarMap) jet.VarMap { - vars.Set("inc", func(i int) int { - return i + 1 - }) - vars.Set("min", math.Min) - vars.Set("genRoute", func(name string, params ...string) string { - return "error" - }) - vars.Set("getRawQuery", func(currentUrl *url.URL) string { - return currentUrl.RawQuery - }) - vars.Set("genViewTorrentRoute", func(torrent_id uint) string { - // Helper for when you have an uint while genRoute("view_torrent", ...) takes a string - // FIXME better solution? - s := strconv.FormatUint(uint64(torrent_id), 10) - url := "/view/" + s - return url - }) - vars.Set("genSearchWithOrdering", func(currentUrl *url.URL, sortBy string) string { - values := currentUrl.Query() - order := false //Default is DESC - sort := "2" //Default is Date (Actually ID, but Date is the same thing) - - if _, ok := values["order"]; ok { - order, _ = strconv.ParseBool(values["order"][0]) - } - if _, ok := values["sort"]; ok { - sort = values["sort"][0] - } - - if sort == sortBy { - order = !order //Flip order by repeat-clicking - } else { - order = false //Default to descending when sorting by something new - } - - values.Set("sort", sortBy) - values.Set("order", strconv.FormatBool(order)) - - u, _ := url.Parse("/search") - u.RawQuery = values.Encode() - - return u.String() - }) - vars.Set("genSortArrows", func(currentUrl *url.URL, sortBy string) template.HTML { - values := currentUrl.Query() - leftclass := "sortarrowdim" - rightclass := "sortarrowdim" - - order := false - sort := "2" - - if _, ok := values["order"]; ok { - order, _ = strconv.ParseBool(values["order"][0]) - } - if _, ok := values["sort"]; ok { - sort = values["sort"][0] - } - - if sort == sortBy { - if order { - rightclass = "" - } else { - leftclass = "" - } - } - - arrows := "" - - return template.HTML(arrows) - }) - vars.Set("genNav", func(nav Navigation, currentUrl *url.URL, pagesSelectable int) template.HTML { - var ret = "" - if nav.TotalItem > 0 { - maxPages := math.Ceil(float64(nav.TotalItem) / float64(nav.MaxItemPerPage)) - - if nav.CurrentPage-1 > 0 { - url := "/" + nav.Route + "/1" - ret = ret + "
  • «
  • " - } - startValue := 1 - if nav.CurrentPage > pagesSelectable/2 { - startValue = (int(math.Min((float64(nav.CurrentPage)+math.Floor(float64(pagesSelectable)/2)), maxPages)) - pagesSelectable + 1) - } - if startValue < 1 { - startValue = 1 - } - endValue := (startValue + pagesSelectable - 1) - if endValue > int(maxPages) { - endValue = int(maxPages) - } - for i := startValue; i <= endValue; i++ { - pageNum := strconv.Itoa(i) - url := "/" + nav.Route + "/" + pageNum - ret = ret + "" + "" + strconv.Itoa(i) + "" - } - if nav.CurrentPage < int(maxPages) { - url := "/" + nav.Route + "/" + strconv.Itoa(nav.CurrentPage+1) - ret = ret + "
  • »
  • " - } - itemsThisPageStart := nav.MaxItemPerPage*(nav.CurrentPage-1) + 1 - itemsThisPageEnd := nav.MaxItemPerPage * nav.CurrentPage - if nav.TotalItem < itemsThisPageEnd { - itemsThisPageEnd = nav.TotalItem - } - ret = ret + "

    " + strconv.Itoa(itemsThisPageStart) + "-" + strconv.Itoa(itemsThisPageEnd) + "/" + strconv.Itoa(nav.TotalItem) + "

    " - } - return template.HTML(ret) - }) + vars.Set("getRawQuery", getRawQuery) + vars.Set("genSearchWithOrdering", genSearchWithOrdering) + vars.Set("genSortArrows", genSortArrows) + vars.Set("genNav", genNav) vars.Set("Sukebei", config.IsSukebei) vars.Set("getDefaultLanguage", publicSettings.GetDefaultLanguage) - vars.Set("FlagCode", func(languageCode string) string { - return publicSettings.Flag(languageCode, true) - }) - vars.Set("getAvatar", func(hash string, size int) string { - return "https://www.gravatar.com/avatar/" + hash + "?s=" + strconv.Itoa(size) - }) + vars.Set("FlagCode", flagCode) + vars.Set("getAvatar", getAvatar) - vars.Set("NoEncode", func(str string) template.HTML { - return template.HTML(str) - }) - vars.Set("calcWidthSeed", func(seed uint32, leech uint32) float64 { - return float64(float64(seed)/(float64(seed)+float64(leech))) * 100 - }) - vars.Set("calcWidthLeech", func(seed uint32, leech uint32) float64 { - return float64(float64(leech)/(float64(seed)+float64(leech))) * 100 - }) - vars.Set("formatDateRFC", func(t time.Time) string { - // because time.* isn't available in templates... - return t.Format(time.RFC3339) - }) + vars.Set("formatDateRFC", formatDateRFC) vars.Set("GetHostname", format.GetHostname) - vars.Set("GetCategories", func(keepParent bool, keepChild bool) categories.Categories { - return categories.GetSelect(keepParent, keepChild) - }) - vars.Set("GetCategory", func(category string, keepParent bool) (categoryRet categories.Categories) { - cats := categories.GetSelect(true, true) - found := false - categoryRet = make(categories.Categories, len(cats)) - for _, v := range cats { - if v.ID == category+"_" { - found = true - if keepParent { - categoryRet = append(categoryRet, v) - } - } else if len(v.ID) <= 2 && len(categoryRet) > 0 { - break - } else if found { - categoryRet = append(categoryRet, v) - } - } - return - }) - vars.Set("CategoryName", func(category string, sub_category string) string { - s := category + "_" + sub_category - - if category, ok := categories.GetByID(s); ok { - return category.Name - } - return "" - }) + vars.Set("GetCategories", categories.GetSelect) + vars.Set("GetCategory", getCategory) + vars.Set("CategoryName", categoryName) vars.Set("GetTorrentLanguages", torrentLanguages.GetTorrentLanguages) - vars.Set("LanguageName", func(lang publicSettings.Language, T publicSettings.TemplateTfunc) string { - if strings.Contains(lang.Name, ",") { - langs := strings.Split(lang.Name, ", ") - tags := strings.Split(lang.Tag, ", ") - for k := range langs { - langs[k] = strings.Title(publicSettings.Translate(tags[k], string(T("language_code")))) - } - return strings.Join(langs, ", ") - } - return strings.Title(lang.Translate(T("language_code"))) - }) - vars.Set("LanguageNameFromCode", func(languageCode string, T publicSettings.TemplateTfunc) string { - if strings.Contains(languageCode, ",") { - tags := strings.Split(languageCode, ", ") - var langs []string - for k := range langs { - langs = append(langs, strings.Title(publicSettings.Translate(tags[k], string(T("language_code"))))) - } - return strings.Join(langs, ", ") - } - return strings.Title(publicSettings.Translate(languageCode, string(T("language_code")))) - }) - vars.Set("fileSize", func(filesize int64, T publicSettings.TemplateTfunc) template.HTML { - if filesize == 0 { - return T("unknown") - } - return template.HTML(format.FileSize(filesize)) - }) - vars.Set("makeCaptchaData", func(captchaID string, T publicSettings.TemplateTfunc) captchaData { - return captchaData{captchaID, T} - }) - vars.Set("DefaultUserSettings", func(s string) bool { - return config.Get().Users.DefaultUserSettings[s] - }) - vars.Set("makeTreeViewData", func(f *filelist.FileListFolder, nestLevel int, T publicSettings.TemplateTfunc, identifierChain string) interface{} { - return struct { - Folder *filelist.FileListFolder - NestLevel int - T publicSettings.TemplateTfunc - IdentifierChain string - }{f, nestLevel, T, identifierChain} - }) - vars.Set("lastID", func(currentUrl *url.URL, torrents []models.TorrentJSON) int { - values := currentUrl.Query() - - order := false - sort := "2" - - if _, ok := values["order"]; ok { - order, _ = strconv.ParseBool(values["order"][0]) - } - if _, ok := values["sort"]; ok { - sort = values["sort"][0] - } - lastID := 0 - if sort == "2" || sort == "" { - if order { - lastID = int(torrents[len(torrents)-1].ID) - } else if len(torrents) > 0 { - lastID = int(torrents[0].ID) - } - } - return lastID - }) - vars.Set("getReportDescription", func(d string, T publicSettings.TemplateTfunc) string { - if d == "illegal" { - return "Illegal content" - } else if d == "spam" { - return "Spam / Garbage" - } else if d == "wrongcat" { - return "Wrong category" - } else if d == "dup" { - return "Duplicate / Deprecated" - } - return string(T(d)) - }) - vars.Set("genUploaderLink", func(uploaderID uint, uploaderName template.HTML, torrentHidden bool) template.HTML { - uploaderID, username := torrents.HideUser(uploaderID, string(uploaderName), torrentHidden) - if uploaderID == 0 { - return template.HTML(username) - } - url := "/user/" + strconv.Itoa(int(uploaderID)) + "/" + username - - return template.HTML("" + username + "") - }) - vars.Set("genActivityContent", func(a models.Activity, T publicSettings.TemplateTfunc) template.HTML { - return a.ToLocale(T) - }) - vars.Set("contains", func(arr interface{}, comp string) bool { - switch str := arr.(type) { - case string: - if str == comp { - return true - } - case publicSettings.Language: - if str.Code == comp { - return true - } - default: - return false - } - return false - }) + vars.Set("LanguageName", languageName) + vars.Set("LanguageNameFromCode", languageNameFromCode) + vars.Set("fileSize", fileSize) + vars.Set("DefaultUserSettings", defaultUserSettings) + vars.Set("makeTreeViewData", makeTreeViewData) + vars.Set("lastID", lastID) + vars.Set("getReportDescription", getReportDescription) + vars.Set("genUploaderLink", genUploaderLink) + vars.Set("genActivityContent", genActivityContent) + vars.Set("contains", contains) return vars } +func getRawQuery(currentURL *url.URL) string { + return currentURL.RawQuery +} +func genSearchWithOrdering(currentURL *url.URL, sortBy string) string { + values := currentURL.Query() + order := false //Default is DESC + sort := "2" //Default is Date (Actually ID, but Date is the same thing) + + if _, ok := values["order"]; ok { + order, _ = strconv.ParseBool(values["order"][0]) + } + if _, ok := values["sort"]; ok { + sort = values["sort"][0] + } + + if sort == sortBy { + order = !order //Flip order by repeat-clicking + } else { + order = false //Default to descending when sorting by something new + } + + values.Set("sort", sortBy) + values.Set("order", strconv.FormatBool(order)) + + u, _ := url.Parse("/search") + u.RawQuery = values.Encode() + + return u.String() +} + +func genSortArrows(currentURL *url.URL, sortBy string) template.HTML { + values := currentURL.Query() + leftclass := "sortarrowdim" + rightclass := "sortarrowdim" + + order := false + sort := "2" + + if _, ok := values["order"]; ok { + order, _ = strconv.ParseBool(values["order"][0]) + } + if _, ok := values["sort"]; ok { + sort = values["sort"][0] + } + + if sort == sortBy { + if order { + rightclass = "" + } else { + leftclass = "" + } + } + + arrows := "" + + return template.HTML(arrows) +} + +func genNav(nav Navigation, currentURL *url.URL, pagesSelectable int) template.HTML { + var ret = "" + if nav.TotalItem > 0 { + maxPages := math.Ceil(float64(nav.TotalItem) / float64(nav.MaxItemPerPage)) + + if nav.CurrentPage-1 > 0 { + url := "/" + nav.Route + "/1" + ret = ret + "
  • «
  • " + } + startValue := 1 + if nav.CurrentPage > pagesSelectable/2 { + startValue = (int(math.Min((float64(nav.CurrentPage)+math.Floor(float64(pagesSelectable)/2)), maxPages)) - pagesSelectable + 1) + } + if startValue < 1 { + startValue = 1 + } + endValue := (startValue + pagesSelectable - 1) + if endValue > int(maxPages) { + endValue = int(maxPages) + } + for i := startValue; i <= endValue; i++ { + pageNum := strconv.Itoa(i) + url := "/" + nav.Route + "/" + pageNum + ret = ret + "" + "" + strconv.Itoa(i) + "" + } + if nav.CurrentPage < int(maxPages) { + url := "/" + nav.Route + "/" + strconv.Itoa(nav.CurrentPage+1) + ret = ret + "
  • »
  • " + } + itemsThisPageStart := nav.MaxItemPerPage*(nav.CurrentPage-1) + 1 + itemsThisPageEnd := nav.MaxItemPerPage * nav.CurrentPage + if nav.TotalItem < itemsThisPageEnd { + itemsThisPageEnd = nav.TotalItem + } + ret = ret + "

    " + strconv.Itoa(itemsThisPageStart) + "-" + strconv.Itoa(itemsThisPageEnd) + "/" + strconv.Itoa(nav.TotalItem) + "

    " + } + return template.HTML(ret) +} + +func flagCode(languageCode string) string { + return publicSettings.Flag(languageCode, true) +} + +func getAvatar(hash string, size int) string { + return "https://www.gravatar.com/avatar/" + hash + "?s=" + strconv.Itoa(size) +} + +func formatDateRFC(t time.Time) string { + // because time.* isn't available in templates... + return t.Format(time.RFC3339) +} +func getCategory(category string, keepParent bool) categories.Categories { + cats := categories.GetSelect(true, true) + found := false + categoryRet := categories.Categories{} + for _, v := range cats { + if v.ID == category+"_" { + found = true + if keepParent { + categoryRet = append(categoryRet, v) + } + } else if len(v.ID) <= 2 && len(categoryRet) > 0 { + break + } else if found { + categoryRet = append(categoryRet, v) + } + } + return categoryRet +} +func categoryName(category string, subCategory string) string { + s := category + "_" + subCategory + + if category, ok := categories.GetByID(s); ok { + return category.Name + } + return "" +} +func languageName(lang publicSettings.Language, T publicSettings.TemplateTfunc) string { + if strings.Contains(lang.Name, ",") { + langs := strings.Split(lang.Name, ", ") + tags := strings.Split(lang.Tag, ", ") + for k := range langs { + langs[k] = strings.Title(publicSettings.Translate(tags[k], string(T("language_code")))) + } + return strings.Join(langs, ", ") + } + return strings.Title(lang.Translate(T("language_code"))) +} +func languageNameFromCode(languageCode string, T publicSettings.TemplateTfunc) string { + if strings.Contains(languageCode, ",") { + tags := strings.Split(languageCode, ", ") + var langs []string + for k := range tags { + langs = append(langs, strings.Title(publicSettings.Translate(tags[k], string(T("language_code"))))) + } + return strings.Join(langs, ", ") + } + return strings.Title(publicSettings.Translate(languageCode, string(T("language_code")))) +} +func fileSize(filesize int64, T publicSettings.TemplateTfunc) template.HTML { + if filesize == 0 { + return T("unknown") + } + return template.HTML(format.FileSize(filesize)) +} + +func defaultUserSettings(s string) bool { + return config.Get().Users.DefaultUserSettings[s] +} + +func makeTreeViewData(f *filelist.FileListFolder, nestLevel int, T publicSettings.TemplateTfunc, identifierChain string) interface{} { + return struct { + Folder *filelist.FileListFolder + NestLevel int + T publicSettings.TemplateTfunc + IdentifierChain string + }{f, nestLevel, T, identifierChain} +} +func lastID(currentURL *url.URL, torrents []models.TorrentJSON) int { + if len(torrents) == 0 { + return 0 + } + values := currentURL.Query() + + order := false + sort := "2" + + if _, ok := values["order"]; ok { + order, _ = strconv.ParseBool(values["order"][0]) + } + if _, ok := values["sort"]; ok { + sort = values["sort"][0] + } + lastID := 0 + if sort == "2" || sort == "" { + if order { + lastID = int(torrents[len(torrents)-1].ID) + } else if len(torrents) > 0 { + lastID = int(torrents[0].ID) + } + } + return lastID +} +func getReportDescription(d string, T publicSettings.TemplateTfunc) string { + if d == "illegal" { + return "Illegal content" + } else if d == "spam" { + return "Spam / Garbage" + } else if d == "wrongcat" { + return "Wrong category" + } else if d == "dup" { + return "Duplicate / Deprecated" + } + return string(T(d)) +} +func genUploaderLink(uploaderID uint, uploaderName template.HTML, torrentHidden bool) template.HTML { + uploaderID, username := torrents.HideUser(uploaderID, string(uploaderName), torrentHidden) + if uploaderID == 0 { + return template.HTML(username) + } + url := "/user/" + strconv.Itoa(int(uploaderID)) + "/" + username + + return template.HTML("" + username + "") +} +func genActivityContent(a models.Activity, T publicSettings.TemplateTfunc) template.HTML { + return a.ToLocale(T) +} +func contains(arr interface{}, comp string) bool { + switch str := arr.(type) { + case string: + if str == comp { + return true + } + case publicSettings.Language: + if str.Code == comp { + return true + } + default: + return false + } + return false +} diff --git a/templates/template_functions_test.go b/templates/template_functions_test.go new file mode 100644 index 00000000..316d059a --- /dev/null +++ b/templates/template_functions_test.go @@ -0,0 +1,615 @@ +package templates + +import ( + "fmt" + "html/template" + "net/url" + "path" + "testing" + + "time" + + "reflect" + + "github.com/NyaaPantsu/nyaa/config" + "github.com/NyaaPantsu/nyaa/models" + "github.com/NyaaPantsu/nyaa/utils/categories" + "github.com/NyaaPantsu/nyaa/utils/publicSettings" + "github.com/gin-gonic/gin" +) + +// run before router/init.go:init() +var _ = func() (_ struct{}) { + gin.SetMode(gin.TestMode) + config.ConfigPath = path.Join("..", config.ConfigPath) + config.DefaultConfigPath = path.Join("..", config.DefaultConfigPath) + config.Reload() + categories.InitCategories() + return +}() + +func TestGetRawQuery(t *testing.T) { + var tests = []map[string]string{ + { + "test": "", + "expected": "", + }, + { + "test": "http://lol.co/", + "expected": "", + }, + { + "test": "lol.co", + "expected": "", + }, + { + "test": "lol.co?", + "expected": "", + }, + { + "test": "lol.co?why", + "expected": "why", + }, + { + "test": "https://lol.co?why", + "expected": "why", + }, + } + + for _, test := range tests { + url, _ := url.Parse(test["test"]) + value := getRawQuery(url) + if value != test["expected"] { + t.Errorf("Unexpected value from the function getRawQuery, got '%s', wanted '%s' for '%s'", value, test["expected"], test["test"]) + } + } +} + +func TestGenSearchWithOrdering(t *testing.T) { + var tests = []map[string]string{ + { + "test": "", + "mode": "2", + "expected": "/search?order=true&sort=2", + }, + { + "test": "http://lol.co/?s=why&sort=1", + "mode": "2", + "expected": "/search?order=false&s=why&sort=2", + }, + { + "test": "http://lol.co/?s=why&sort=1", + "mode": "1", + "expected": "/search?order=true&s=why&sort=1", + }, + { + "test": "http://lol.co/?s=why&sort=1&order=true", + "mode": "1", + "expected": "/search?order=false&s=why&sort=1", + }, + { + "test": "http://lol.co/?s=why&sort=1&order=false", + "mode": "1", + "expected": "/search?order=true&s=why&sort=1", + }, + { + "test": "http://lol.co/?s=why&sort=1&order=false", + "mode": "2", + "expected": "/search?order=false&s=why&sort=2", + }, + { + "test": "http://lol.co/?s=why&sort=1&order=true", + "mode": "2", + "expected": "/search?order=false&s=why&sort=2", + }, + } + + for _, test := range tests { + url, _ := url.Parse(test["test"]) + value := genSearchWithOrdering(url, test["mode"]) + if value != test["expected"] { + t.Errorf("Unexpected value from the function genSearchWithOrdering, got '%s', wanted '%s' for '%s' and '%s'", value, test["expected"], test["test"], test["mode"]) + } + } +} + +func TestFlagCode(t *testing.T) { + var tests = []map[string]string{ + { + "test": "", + "expected": "und", + }, + { + "test": "es", + "expected": "es", + }, + { + "test": "lol", + "expected": "lol", + }, + { + "test": "fr-fr", + "expected": "fr", + }, + { + "test": "fr-lol", + "expected": "lol", + }, + { + "test": "ca-es", + "expected": "ca", + }, + { + "test": "es-mx", + "expected": "es", + }, + } + + for _, test := range tests { + value := flagCode(test["test"]) + if value != test["expected"] { + t.Errorf("Unexpected value from the function flagCode, got '%s', wanted '%s' for '%s'", value, test["expected"], test["test"]) + } + } +} + +func TestGetAvatar(t *testing.T) { + var tests = []struct { + Test string + Size int + Expected string + }{ + { + Test: "", + Size: 0, + Expected: "https://www.gravatar.com/avatar/?s=0", + }, + { + Test: "", + Size: 100, + Expected: "https://www.gravatar.com/avatar/?s=100", + }, + { + Test: "test", + Size: 100, + Expected: "https://www.gravatar.com/avatar/test?s=100", + }, + { + Test: "test", + Size: 0, + Expected: "https://www.gravatar.com/avatar/test?s=0", + }, + } + + for _, test := range tests { + value := getAvatar(test.Test, test.Size) + if value != test.Expected { + t.Errorf("Unexpected value from the function getAvatar, got '%s', wanted '%s' for '%s' and '%d'", value, test.Expected, test.Test, test.Size) + } + } +} + +func TestFormatDateRFC(t *testing.T) { + location, _ := time.LoadLocation("UTC") + var tests = []struct { + Test time.Time + Expected string + }{ + { + Test: time.Date(2016, 5, 4, 3, 2, 1, 10, location), + Expected: "2016-05-04T03:02:01Z", + }, + { + Test: time.Now(), + Expected: time.Now().Format(time.RFC3339), + }, + } + + for _, test := range tests { + value := formatDateRFC(test.Test) + if value != test.Expected { + t.Errorf("Unexpected value from the function formatDateRFC, got '%s', wanted '%s' for '%s'", value, test.Expected, test.Test.String()) + } + } +} + +func TestGetCategory(t *testing.T) { + var tests = []struct { + TestCat string + TestParent bool + Expected categories.Categories + }{ + { + TestCat: "", + TestParent: false, + Expected: categories.Categories{}, + }, + { + TestCat: "", + TestParent: true, + Expected: categories.Categories{}, + }, + { + TestCat: "3_12", + TestParent: false, + Expected: categories.Categories{}, + }, + { + TestCat: "3", + TestParent: false, + Expected: categories.Categories{ + {"3_12", "anime_amv"}, + {"3_5", "anime_english_translated"}, + {"3_13", "anime_non_english_translated"}, + {"3_6", "anime_raw"}, + }, + }, + { + TestCat: "3", + TestParent: true, + Expected: categories.Categories{ + {"3_", "anime"}, + {"3_12", "anime_amv"}, + {"3_5", "anime_english_translated"}, + {"3_13", "anime_non_english_translated"}, + {"3_6", "anime_raw"}, + }, + }, + } + for _, test := range tests { + value := getCategory(test.TestCat, test.TestParent) + if !reflect.DeepEqual(value, test.Expected) { + t.Errorf("Unexpected value from the function getCategory, got '%v', wanted '%v' for '%s' and '%t'", value, test.Expected, test.TestCat, test.TestParent) + } + } +} + +func TestCategoryName(t *testing.T) { + var tests = []struct { + TestCat string + TestSubCat string + Expected string + }{ + { + TestCat: "", + TestSubCat: "", + Expected: "", + }, + { + TestCat: "d", + TestSubCat: "s", + Expected: "", + }, + { + TestCat: "3", + TestSubCat: "", + Expected: "anime", + }, + { + TestCat: "3", + TestSubCat: "6", + Expected: "anime_raw", + }, + } + + for _, test := range tests { + value := categoryName(test.TestCat, test.TestSubCat) + if value != test.Expected { + t.Errorf("Unexpected value from the function categoryName, got '%s', wanted '%s' for '%s' and '%s'", value, test.Expected, test.TestCat, test.TestSubCat) + } + } +} + +func TestLanguageName(t *testing.T) { + var tests = []struct { + TestLang publicSettings.Language + Expected string + }{ + { + TestLang: publicSettings.Language{"", "", ""}, + Expected: "", + }, + { + TestLang: publicSettings.Language{"", "fr", "fr-fr"}, + Expected: "French (France)", + }, + { + TestLang: publicSettings.Language{"", "fr", "fr"}, + Expected: "French", + }, + { + TestLang: publicSettings.Language{"something, something", "es", "es, es-mx"}, + Expected: "Spanish, Mexican Spanish", + }, + } + T := mockupTemplateT(t) + for _, test := range tests { + value := languageName(test.TestLang, T) + if value != test.Expected { + t.Errorf("Unexpected value from the function languageName, got '%s', wanted '%s' for '%v'", value, test.Expected, test.TestLang) + } + } +} + +func TestLanguageNameFromCode(t *testing.T) { + var tests = []struct { + TestLang string + Expected string + }{ + { + TestLang: "", + Expected: "", + }, + { + TestLang: "fr-fr", + Expected: "French (France)", + }, + { + TestLang: "ofjd", + Expected: "", + }, + { + TestLang: "fr", + Expected: "French", + }, + { + TestLang: "es, es-mx", + Expected: "Spanish, Mexican Spanish", + }, + } + T := mockupTemplateT(t) + for _, test := range tests { + value := languageNameFromCode(test.TestLang, T) + if value != test.Expected { + t.Errorf("Unexpected value from the function languageName, got '%s', wanted '%s' for '%s'", value, test.Expected, test.TestLang) + } + } +} + +func TestFileSize(t *testing.T) { + var tests = []struct { + TestSize int64 + Expected template.HTML + }{ + { + TestSize: 0, + Expected: template.HTML("Unknown"), + }, + { + TestSize: 10, + Expected: template.HTML("10.0 B"), + }, + } + T := mockupTemplateT(t) + for _, test := range tests { + value := fileSize(test.TestSize, T) + if value != test.Expected { + t.Errorf("Unexpected value from the function languageName, got '%s', wanted '%s' for '%d'", value, test.Expected, test.TestSize) + } + } +} + +func TestLastID(t *testing.T) { + var tests = []struct { + TestTorrents []models.TorrentJSON + TestURL string + Expected int + }{ + { + TestTorrents: []models.TorrentJSON{{ID: 3}, {ID: 1}}, + TestURL: "?sort=&order=", + Expected: 3, + }, + { + TestTorrents: []models.TorrentJSON{{ID: 3}, {ID: 1}}, + TestURL: "?sort=2&order=", + Expected: 3, + }, + { + TestTorrents: []models.TorrentJSON{{ID: 1}, {ID: 3}}, + TestURL: "?sort=2&order=true", + Expected: 3, + }, + { + TestTorrents: []models.TorrentJSON{{ID: 1}, {ID: 3}}, + TestURL: "?sort=3&order=true", + Expected: 0, + }, + { + TestTorrents: []models.TorrentJSON{}, + TestURL: "?sort=2&order=true", + Expected: 0, + }, + { + TestTorrents: []models.TorrentJSON{}, + TestURL: "?sort=2&order=false", + Expected: 0, + }, + } + for _, test := range tests { + url, _ := url.Parse(test.TestURL) + value := lastID(url, test.TestTorrents) + if value != test.Expected { + t.Errorf("Unexpected value from the function languageName, got '%d', wanted '%d' for '%s' and '%v'", value, test.Expected, test.TestURL, test.TestTorrents) + } + } +} + +func TestGetReportDescription(t *testing.T) { + var tests = []struct { + TestDesc string + Expected string + }{ + { + TestDesc: "", + Expected: "", + }, + { + TestDesc: "illegal", + Expected: "Illegal content", + }, + { + TestDesc: "spam", + Expected: "Spam / Garbage", + }, + { + TestDesc: "wrongcat", + Expected: "Wrong category", + }, + { + TestDesc: "dup", + Expected: "Duplicate / Deprecated", + }, + { + TestDesc: "illegal_content", + Expected: "Illegal content", + }, + { + TestDesc: "spam_garbage", + Expected: "Spam / Garbage", + }, + { + TestDesc: "wrong_category", + Expected: "Wrong category", + }, + { + TestDesc: "duplicate_deprecated", + Expected: "Duplicate / Deprecated", + }, + } + T := mockupTemplateT(t) + for _, test := range tests { + value := getReportDescription(test.TestDesc, T) + if value != test.Expected { + t.Errorf("Unexpected value from the function languageName, got '%s', wanted '%s' for '%s'", value, test.Expected, test.TestDesc) + } + } +} + +func TestGenUploaderLink(t *testing.T) { + var tests = []struct { + TestID uint + TestName template.HTML + TestHidden bool + Expected template.HTML + }{ + { + TestID: 0, + TestName: template.HTML(""), + TestHidden: false, + Expected: template.HTML("れんちょん"), + }, + { + TestID: 10, + TestName: template.HTML("dd"), + TestHidden: true, + Expected: template.HTML("れんちょん"), + }, + { + TestID: 10, + TestName: template.HTML("dd"), + TestHidden: false, + Expected: template.HTML("dd"), + }, + { + TestID: 0, // Old Uploader + TestName: template.HTML("dd"), + TestHidden: false, + Expected: template.HTML("dd"), + }, + { + TestID: 10, + TestName: template.HTML(""), + TestHidden: false, + Expected: template.HTML("れんちょん"), + }, + { + TestID: 10, + TestName: template.HTML(""), + TestHidden: true, + Expected: template.HTML("れんちょん"), + }, + } + for _, test := range tests { + value := genUploaderLink(test.TestID, test.TestName, test.TestHidden) + if value != test.Expected { + t.Errorf("Unexpected value from the function languageName, got '%s', wanted '%s' for '%d' and '%s' and '%t'", string(value), string(test.Expected), test.TestID, string(test.TestName), test.TestHidden) + } + } +} + +func TestContains(t *testing.T) { + var tests = []struct { + TestArr interface{} + TestComp string + Expected bool + }{ + { + TestArr: "kilo", + TestComp: "kilo", + Expected: true, + }, + { + TestArr: "kilo", + TestComp: "loki", // Clearly not the same level + Expected: false, + }, + { + TestArr: "kilo", + TestComp: "kiloo", + Expected: false, + }, + { + TestArr: publicSettings.Language{Code: "kilo"}, + TestComp: "kilo", + Expected: true, + }, + { + TestArr: publicSettings.Language{Code: "kilo"}, + TestComp: "loki", // Clearly not the same level + Expected: false, + }, + { + TestArr: publicSettings.Language{Code: "kilo"}, + TestComp: "kiloo", + Expected: false, + }, + { + TestArr: "kilo", + TestComp: "", + Expected: false, + }, + { + TestArr: publicSettings.Language{Code: "kilo"}, + TestComp: "", + Expected: false, + }, + } + for _, test := range tests { + value := contains(test.TestArr, test.TestComp) + if value != test.Expected { + t.Errorf("Unexpected value from the function languageName, got '%t', wanted '%t' for '%v' and '%s'", value, test.Expected, test.TestArr, test.TestComp) + } + } +} + +func mockupTemplateT(t *testing.T) publicSettings.TemplateTfunc { + conf := config.Get().I18n + conf.Directory = path.Join("..", conf.Directory) + var retriever publicSettings.UserRetriever // not required during initialization + + err := publicSettings.InitI18n(conf, retriever) + if err != nil { + t.Errorf("failed to initialize language translations: %v", err) + } + + Ts, _, err := publicSettings.TfuncAndLanguageWithFallback("en-us") + if err != nil { + t.Error("Couldn't load language files!") + } + var T publicSettings.TemplateTfunc + T = func(id string, args ...interface{}) template.HTML { + return template.HTML(fmt.Sprintf(Ts(id), args...)) + } + return T +} diff --git a/utils/categories/categories.go b/utils/categories/categories.go index 59f0a99d..3155f80b 100644 --- a/utils/categories/categories.go +++ b/utils/categories/categories.go @@ -18,7 +18,8 @@ type Categories []Category var categories Categories var Index map[string]int -func initCategories() { +// InitCategories init the categories and index variables. Exported for tests +func InitCategories() { var cats map[string]string if config.IsSukebei() { cats = config.Get().Torrents.SukebeiCategories @@ -43,11 +44,14 @@ func initCategories() { } } +func init() { + if len(categories) == 0 { + InitCategories() + } +} + // All : function to get all categories depending on the actual website from config/categories.go func All() Categories { - if len(categories) == 0 { - initCategories() - } return categories } @@ -56,7 +60,7 @@ func Get(key int) Category { return All()[key] } -// Get : function to get a category by the id of the category from the database +// GetByID : function to get a category by the id of the category from the database func GetByID(id string) (Category, bool) { if key, ok := Index[id]; ok { return All()[key], true