scraper_test.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package scraper // import "miniflux.app/v2/internal/reader/scraper"
  4. import (
  5. "bytes"
  6. "os"
  7. "strings"
  8. "testing"
  9. "github.com/andybalholm/cascadia"
  10. )
  11. func TestPredefinedRulesAreValidSelectors(t *testing.T) {
  12. for domain, rules := range predefinedRules {
  13. if _, err := cascadia.Compile(rules); err != nil {
  14. t.Errorf("Predefined scraper rules for %s are not a valid CSS selector: %v", domain, err)
  15. }
  16. }
  17. }
  18. func TestGetPredefinedRules(t *testing.T) {
  19. if getPredefinedScraperRules("http://www.phoronix.com/") == "" {
  20. t.Error("Unable to find rule for phoronix.com")
  21. }
  22. if getPredefinedScraperRules("https://www.linux.com/") == "" {
  23. t.Error("Unable to find rule for linux.com")
  24. }
  25. if getPredefinedScraperRules("https://linux.com/") == "" {
  26. t.Error("Unable to find rule for linux.com")
  27. }
  28. if getPredefinedScraperRules("https://example.org/") != "" {
  29. t.Error("A rule not defined should not return anything")
  30. }
  31. }
  32. func TestWhitelistedContentTypes(t *testing.T) {
  33. scenarios := map[string]bool{
  34. "text/html": true,
  35. "TeXt/hTmL": true,
  36. "application/xhtml+xml": true,
  37. "text/html; charset=utf-8": true,
  38. "application/xhtml+xml; charset=utf-8": true,
  39. "text/css": false,
  40. "application/javascript": false,
  41. "image/png": false,
  42. "application/pdf": false,
  43. }
  44. for inputValue, expectedResult := range scenarios {
  45. actualResult := isAllowedContentType(inputValue)
  46. if actualResult != expectedResult {
  47. t.Errorf(`Unexpected result for content type whitelist, got "%v" instead of "%v"`, actualResult, expectedResult)
  48. }
  49. }
  50. }
  51. func TestSelectorRules(t *testing.T) {
  52. var ruleTestCases = map[string]string{
  53. "img.html": "article > img",
  54. "iframe.html": "article > iframe",
  55. "p.html": "article > p",
  56. }
  57. for filename, rule := range ruleTestCases {
  58. html, err := os.ReadFile("testdata/" + filename)
  59. if err != nil {
  60. t.Fatalf(`Unable to read file %q: %v`, filename, err)
  61. }
  62. _, actualResult, err := findContentUsingCustomRules(bytes.NewReader(html), rule)
  63. if err != nil {
  64. t.Fatalf(`Scraping error for %q - %q: %v`, filename, rule, err)
  65. }
  66. expectedResult, err := os.ReadFile("testdata/" + filename + "-result")
  67. if err != nil {
  68. t.Fatalf(`Unable to read file %q: %v`, filename, err)
  69. }
  70. if actualResult != strings.TrimSpace(string(expectedResult)) {
  71. t.Errorf(`Unexpected result for %q, got %q instead of %q`, rule, actualResult, expectedResult)
  72. }
  73. }
  74. }
  75. func TestParseBaseURLWithCustomRules(t *testing.T) {
  76. html := `<html><head><base href="https://example.com/"></head><body><img src="image.jpg"></body></html>`
  77. baseURL, _, err := findContentUsingCustomRules(strings.NewReader(html), "img")
  78. if err != nil {
  79. t.Fatalf(`Scraping error: %v`, err)
  80. }
  81. if baseURL != "https://example.com/" {
  82. t.Errorf(`Unexpected base URL, got %q instead of "https://example.com/"`, baseURL)
  83. }
  84. }
  85. func TestParseMultipleBaseURLWithCustomRules(t *testing.T) {
  86. html := `<html><head><base href="https://example.com/"><base href="https://example.org/"/></head><body><img src="image.jpg"></body></html>`
  87. baseURL, _, err := findContentUsingCustomRules(strings.NewReader(html), "img")
  88. if err != nil {
  89. t.Fatalf(`Scraping error: %v`, err)
  90. }
  91. if baseURL != "https://example.com/" {
  92. t.Errorf(`Unexpected base URL, got %q instead of "https://example.com/"`, baseURL)
  93. }
  94. }
  95. func TestParseRelativeBaseURLWithCustomRules(t *testing.T) {
  96. html := `<html><head><base href="/test"></head><body><img src="image.jpg"></body></html>`
  97. baseURL, _, err := findContentUsingCustomRules(strings.NewReader(html), "img")
  98. if err != nil {
  99. t.Fatalf(`Scraping error: %v`, err)
  100. }
  101. if baseURL != "" {
  102. t.Errorf(`Unexpected base URL, got %q`, baseURL)
  103. }
  104. }
  105. func TestParseEmptyBaseURLWithCustomRules(t *testing.T) {
  106. html := `<html><head><base href=" "></head><body><img src="image.jpg"></body></html>`
  107. baseURL, _, err := findContentUsingCustomRules(strings.NewReader(html), "img")
  108. if err != nil {
  109. t.Fatalf(`Scraping error: %v`, err)
  110. }
  111. if baseURL != "" {
  112. t.Errorf(`Unexpected base URL, got %q instead of ""`, baseURL)
  113. }
  114. }
  115. func TestParseMissingBaseURLWithCustomRules(t *testing.T) {
  116. html := `<html><head></head><body><img src="image.jpg"></body></html>`
  117. baseURL, _, err := findContentUsingCustomRules(strings.NewReader(html), "img")
  118. if err != nil {
  119. t.Fatalf(`Scraping error: %v`, err)
  120. }
  121. if baseURL != "" {
  122. t.Errorf(`Unexpected base URL, got %q instead of ""`, baseURL)
  123. }
  124. }