You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
4.8 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. package rssbot
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "io/ioutil"
  7. "net/http"
  8. "strings"
  9. "sync"
  10. "testing"
  11. "time"
  12. "github.com/matrix-org/go-neb/database"
  13. "github.com/matrix-org/go-neb/testutils"
  14. "github.com/matrix-org/go-neb/types"
  15. "github.com/matrix-org/gomatrix"
  16. )
  17. const rssFeedXML = `
  18. <?xml version="1.0" encoding="UTF-8"?>
  19. <rss version="2.0"
  20. xmlns:content="http://purl.org/rss/1.0/modules/content/"
  21. xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  22. xmlns:dc="http://purl.org/dc/elements/1.1/"
  23. xmlns:atom="http://www.w3.org/2005/Atom"
  24. xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
  25. xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  26. >
  27. <channel>
  28. <title>Mask Shop</title>
  29. <item>
  30. <title>New Item: Majora&#8217;s Mask</title>
  31. <link>http://go.neb/rss/majoras-mask</link>
  32. <author>The Skullkid!</author>
  33. </item>
  34. </channel>
  35. </rss>`
  36. func createRSSClient(t *testing.T, feedURL string) *Service {
  37. database.SetServiceDB(&database.NopStorage{})
  38. // Replace the cachingClient with a mock so we can intercept RSS requests
  39. rssTrans := testutils.NewRoundTripper(func(req *http.Request) (*http.Response, error) {
  40. if req.URL.String() != feedURL {
  41. return nil, errors.New("Unknown test URL")
  42. }
  43. return &http.Response{
  44. StatusCode: 200,
  45. Body: ioutil.NopCloser(bytes.NewBufferString(rssFeedXML)),
  46. }, nil
  47. })
  48. cachingClient = &http.Client{Transport: rssTrans}
  49. // Create the RSS service
  50. srv, err := types.CreateService("id", "rssbot", "@happy_mask_salesman:hyrule", []byte(
  51. `{"feeds": {"`+feedURL+`":{}}}`, // no config yet
  52. ))
  53. if err != nil {
  54. t.Fatal(err)
  55. }
  56. rssbot := srv.(*Service)
  57. // Configure the service to force OnPoll to query the RSS feed and attempt to send results
  58. // to the right room.
  59. f := rssbot.Feeds[feedURL]
  60. f.Rooms = []string{"!linksroom:hyrule"}
  61. f.NextPollTimestampSecs = time.Now().Unix()
  62. rssbot.Feeds[feedURL] = f
  63. return rssbot
  64. }
  65. func TestHTMLEntities(t *testing.T) {
  66. feedURL := "https://thehappymaskshop.hyrule"
  67. rssbot := createRSSClient(t, feedURL)
  68. // Create the Matrix client which will send the notification
  69. wg := sync.WaitGroup{}
  70. wg.Add(1)
  71. matrixTrans := struct{ testutils.MockTransport }{}
  72. matrixTrans.RT = func(req *http.Request) (*http.Response, error) {
  73. if strings.HasPrefix(req.URL.Path, "/_matrix/client/r0/rooms/!linksroom:hyrule/send/m.room.message") {
  74. // Check content body to make sure it is decoded
  75. var msg gomatrix.HTMLMessage
  76. if err := json.NewDecoder(req.Body).Decode(&msg); err != nil {
  77. t.Fatal("Failed to decode request JSON: ", err)
  78. return nil, errors.New("Error handling matrix client test request")
  79. }
  80. want := "New Item: Majora\u2019s Mask" // 0x2019 = 8217
  81. if !strings.Contains(msg.Body, want) {
  82. t.Errorf("TestHTMLEntities: want '%s' in body, got '%s'", want, msg.Body)
  83. }
  84. wg.Done()
  85. return &http.Response{
  86. StatusCode: 200,
  87. Body: ioutil.NopCloser(bytes.NewBufferString(`
  88. {"event_id":"$123456:hyrule"}
  89. `)),
  90. }, nil
  91. }
  92. return nil, errors.New("Unhandled matrix client test request")
  93. }
  94. matrixClient, _ := gomatrix.NewClient("https://hyrule", "@happy_mask_salesman:hyrule", "its_a_secret")
  95. matrixClient.Client = &http.Client{Transport: matrixTrans}
  96. // Invoke OnPoll to trigger the RSS feed update
  97. _ = rssbot.OnPoll(matrixClient)
  98. // Check that the Matrix client sent a message
  99. wg.Wait()
  100. }
  101. func TestFeedItemFiltering(t *testing.T) {
  102. feedURL := "https://thehappymaskshop.hyrule"
  103. // Create rssbot client
  104. rssbot := createRSSClient(t, feedURL)
  105. feed := rssbot.Feeds[feedURL]
  106. feed.MustInclude.Title = []string{"Zelda"}
  107. rssbot.Feeds[feedURL] = feed
  108. _, items, _ := rssbot.queryFeed(feedURL)
  109. // Expect that we get no items if we filter for 'Zelda' in title
  110. if len(items) != 0 {
  111. t.Errorf("Expected 0 items, got %v", items)
  112. }
  113. // Recreate rssbot client
  114. rssbot = createRSSClient(t, feedURL)
  115. feed = rssbot.Feeds[feedURL]
  116. feed.MustInclude.Title = []string{"Majora"}
  117. rssbot.Feeds[feedURL] = feed
  118. _, items, _ = rssbot.queryFeed(feedURL)
  119. // Expect one item if we filter for 'Majora' in title
  120. if len(items) != 1 {
  121. t.Errorf("Expected 1 item, got %d", len(items))
  122. }
  123. // Recreate rssbot client
  124. rssbot = createRSSClient(t, feedURL)
  125. feed = rssbot.Feeds[feedURL]
  126. feed.MustNotInclude.Author = []string{"kid"}
  127. rssbot.Feeds[feedURL] = feed
  128. _, items, _ = rssbot.queryFeed(feedURL)
  129. // 'kid' does not match an entire word in the author name, so it's not filtered
  130. if len(items) != 1 {
  131. t.Errorf("Expected 1 item, got %d", len(items))
  132. }
  133. // Recreate rssbot client
  134. rssbot = createRSSClient(t, feedURL)
  135. feed = rssbot.Feeds[feedURL]
  136. feed.MustNotInclude.Author = []string{"Skullkid"}
  137. rssbot.Feeds[feedURL] = feed
  138. _, items, _ = rssbot.queryFeed(feedURL)
  139. // Expect no items if we filter for 'Skullkid' not in author name
  140. if len(items) != 0 {
  141. t.Errorf("Expected 0 items, got %v", items)
  142. }
  143. }