// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. // SPDX-License-Identifier: Apache-2.0 package rewrite // import "miniflux.app/v2/internal/reader/rewrite" import ( "os" "reflect" "strings" "testing" "miniflux.app/v2/internal/config" "miniflux.app/v2/internal/model" ) func TestParseRules(t *testing.T) { rulesText := `add_dynamic_image,replace("article/(.*).svg"|"article/$1.png"),remove(".spam, .ads:not(.keep)")` expected := []rule{ {name: "add_dynamic_image"}, {name: "replace", args: []string{"article/(.*).svg", "article/$1.png"}}, {name: "remove", args: []string{".spam, .ads:not(.keep)"}}, } actual := parseRules(rulesText) if !reflect.DeepEqual(expected, actual) { t.Errorf(`Parsed rules do not match expected rules: got %v instead of %v`, actual, expected) } } func TestReplaceTextLinks(t *testing.T) { scenarios := map[string]string{ `This is a link to example.org`: `This is a link to example.org`, `This is a link to ftp://example.org`: `This is a link to ftp://example.org`, `This is a link to www.example.org`: `This is a link to www.example.org`, `This is a link to http://example.org`: `This is a link to http://example.org`, `This is a link to http://example.org, end of sentence.`: `This is a link to http://example.org, end of sentence.`, `This is a link to https://example.org`: `This is a link to https://example.org`, `This is a link to https://www.example.org/path/to?q=s`: `This is a link to https://www.example.org/path/to?q=s`, `This is a link to https://example.org/index#hash-tag, http://example.org/.`: `This is a link to https://example.org/index#hash-tag, http://example.org/.`, } for input, expected := range scenarios { actual := replaceTextLinks(input) if actual != expected { t.Errorf(`Unexpected link replacement, got "%s" instead of "%s"`, actual, expected) } } } func TestRewriteWithNoMatchingRule(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Some text.`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Some text.`, } ApplyContentRewriteRules(testEntry, ``) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteYoutubeVideoLink(t *testing.T) { config.Opts = config.NewOptions() controlEntry := &model.Entry{ URL: "https://www.youtube.com/watch?v=1234", Title: `A title`, Content: `
Video Description`, } testEntry := &model.Entry{ URL: "https://www.youtube.com/watch?v=1234", Title: `A title`, Content: `Video Description`, } ApplyContentRewriteRules(testEntry, ``) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteYoutubeShortLink(t *testing.T) { config.Opts = config.NewOptions() controlEntry := &model.Entry{ URL: "https://www.youtube.com/shorts/1LUWKWZkPjo", Title: `A title`, Content: `
Video Description`, } testEntry := &model.Entry{ URL: "https://www.youtube.com/shorts/1LUWKWZkPjo", Title: `A title`, Content: `Video Description`, } ApplyContentRewriteRules(testEntry, ``) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteIncorrectYoutubeLink(t *testing.T) { config.Opts = config.NewOptions() controlEntry := &model.Entry{ URL: "https://www.youtube.com/some-page", Title: `A title`, Content: `Video Description`, } testEntry := &model.Entry{ URL: "https://www.youtube.com/some-page", Title: `A title`, Content: `Video Description`, } ApplyContentRewriteRules(testEntry, ``) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteYoutubeLinkAndCustomEmbedURL(t *testing.T) { os.Clearenv() os.Setenv("YOUTUBE_EMBED_URL_OVERRIDE", "https://invidious.custom/embed/") var err error parser := config.NewParser() config.Opts, err = parser.ParseEnvironmentVariables() if err != nil { t.Fatalf(`Parsing failure: %v`, err) } controlEntry := &model.Entry{ URL: "https://www.youtube.com/watch?v=1234", Title: `A title`, Content: `
Video Description`, } testEntry := &model.Entry{ URL: "https://www.youtube.com/watch?v=1234", Title: `A title`, Content: `Video Description`, } ApplyContentRewriteRules(testEntry, ``) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteYoutubeVideoLinkUsingInvidious(t *testing.T) { config.Opts = config.NewOptions() controlEntry := &model.Entry{ URL: "https://www.youtube.com/watch?v=1234", Title: `A title`, Content: `
Video Description`, } testEntry := &model.Entry{ URL: "https://www.youtube.com/watch?v=1234", Title: `A title`, Content: `Video Description`, } ApplyContentRewriteRules(testEntry, `add_youtube_video_using_invidious_player`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteYoutubeShortLinkUsingInvidious(t *testing.T) { config.Opts = config.NewOptions() controlEntry := &model.Entry{ URL: "https://www.youtube.com/shorts/1LUWKWZkPjo", Title: `A title`, Content: `
Video Description`, } testEntry := &model.Entry{ URL: "https://www.youtube.com/shorts/1LUWKWZkPjo", Title: `A title`, Content: `Video Description`, } ApplyContentRewriteRules(testEntry, `add_youtube_video_using_invidious_player`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestAddYoutubeVideoFromId(t *testing.T) { config.Opts = config.NewOptions() scenarios := map[string]string{ // Test with single YouTube ID `Some content with youtube ID `: `
Some content with youtube ID `, // Test with multiple YouTube IDs `Content with youtube_id: "dQw4w9WgXcQ" and youtube_id: "jNQXAC9IVRw"`: `

Content with youtube_id: "dQw4w9WgXcQ" and youtube_id: "jNQXAC9IVRw"`, // Test with YouTube ID using equals sign `Some content with youtube_id = "dQw4w9WgXcQ"`: `
Some content with youtube_id = "dQw4w9WgXcQ"`, // Test with spaces around delimiters `Some content with youtube_id : "dQw4w9WgXcQ"`: `
Some content with youtube_id : "dQw4w9WgXcQ"`, // Test with YouTube ID without quotes (regex requires quotes) `Some content with youtube_id: dQw4w9WgXcQ and more`: `Some content with youtube_id: dQw4w9WgXcQ and more`, // Test with no YouTube ID `Some regular content without any video ID`: `Some regular content without any video ID`, // Test with invalid YouTube ID (wrong length) `Some content with youtube_id: "invalid"`: `Some content with youtube_id: "invalid"`, // Test with empty content ``: ``, } for input, expected := range scenarios { actual := addYoutubeVideoFromId(input) if actual != expected { t.Errorf(`addYoutubeVideoFromId test failed for input "%s"`, input) t.Errorf(`Expected: "%s"`, expected) t.Errorf(`Actual: "%s"`, actual) } } } func TestAddYoutubeVideoFromIdWithCustomEmbedURL(t *testing.T) { os.Clearenv() os.Setenv("YOUTUBE_EMBED_URL_OVERRIDE", "https://invidious.custom/embed/") var err error parser := config.NewParser() config.Opts, err = parser.ParseEnvironmentVariables() if err != nil { t.Fatalf(`Parsing failure: %v`, err) } input := `Some content with youtube_id: "dQw4w9WgXcQ"` expected := `
Some content with youtube_id: "dQw4w9WgXcQ"` actual := addYoutubeVideoFromId(input) if actual != expected { t.Errorf(`addYoutubeVideoFromId with custom embed URL failed`) t.Errorf(`Expected: "%s"`, expected) t.Errorf(`Actual: "%s"`, actual) } } func TestAddInvidiousVideo(t *testing.T) { scenarios := map[string][]string{ // Test with various Invidious instances "https://invidious.io/watch?v=dQw4w9WgXcQ": { "Some video content", `
Some video content`, }, "https://yewtu.be/watch?v=jNQXAC9IVRw": { "Another video description", `
Another video description`, }, "http://invidious.snopyta.org/watch?v=dQw4w9WgXcQ": { "HTTP instance test", `
HTTP instance test`, }, "https://youtube.com/watch?v=dQw4w9WgXcQ": { "YouTube URL (also matches regex)", `
YouTube URL (also matches regex)`, }, "https://example.org/watch?v=dQw4w9WgXcQ": { "Any domain with watch pattern", `
Any domain with watch pattern`, }, // Test with query parameters "https://invidious.io/watch?v=dQw4w9WgXcQ&t=30s": { "Video with timestamp", `
Video with timestamp`, }, // Test with more complex query parameters "https://invidious.io/watch?v=dQw4w9WgXcQ&t=30s&autoplay=1": { "Video with multiple parameters", `
Video with multiple parameters`, }, // Test with non-matching URLs (should return content unchanged) "https://invidious.io/": { "Invidious homepage", "Invidious homepage", }, "https://invidious.io/some-other-page": { "Other page", "Other page", }, "https://invidious.io/search?q=test": { "Search page", "Search page", }, // Test with empty content "https://empty.invidious.io/watch?v=dQw4w9WgXcQ": { "", `
`, }, } for entryURL, testData := range scenarios { entryContent := testData[0] expected := testData[1] actual := addInvidiousVideo(entryURL, entryContent) if actual != expected { t.Errorf(`addInvidiousVideo test failed for URL "%s" and content "%s"`, entryURL, entryContent) t.Errorf(`Expected: "%s"`, expected) t.Errorf(`Actual: "%s"`, actual) } } } func TestRewriteWithInexistingCustomRule(t *testing.T) { controlEntry := &model.Entry{ URL: "https://www.youtube.com/watch?v=1234", Title: `A title`, Content: `Video Description`, } testEntry := &model.Entry{ URL: "https://www.youtube.com/watch?v=1234", Title: `A title`, Content: `Video Description`, } ApplyContentRewriteRules(testEntry, `some rule`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithXkcdLink(t *testing.T) { controlEntry := &model.Entry{ URL: "https://xkcd.com/1912/", Title: `A title`, Content: `
Your problem is so terrible, I worry that, if I help you, I risk drawing the attention of whatever god of technology inflicted it on you.

Your problem is so terrible, I worry that, if I help you, I risk drawing the attention of whatever god of technology inflicted it on you.

`, } testEntry := &model.Entry{ URL: "https://xkcd.com/1912/", Title: `A title`, Content: `Your problem is so terrible, I worry that, if I help you, I risk drawing the attention of whatever god of technology inflicted it on you.`, } ApplyContentRewriteRules(testEntry, ``) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithXkcdLinkHtmlInjection(t *testing.T) { controlEntry := &model.Entry{ URL: "https://xkcd.com/1912/", Title: `A title`, Content: `
<foo>

<foo>

`, } testEntry := &model.Entry{ URL: "https://xkcd.com/1912/", Title: `A title`, Content: `<foo>`, } ApplyContentRewriteRules(testEntry, ``) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithXkcdLinkAndImageNoTitle(t *testing.T) { controlEntry := &model.Entry{ URL: "https://xkcd.com/1912/", Title: `A title`, Content: `Your problem is so terrible, I worry that, if I help you, I risk drawing the attention of whatever god of technology inflicted it on you.`, } testEntry := &model.Entry{ URL: "https://xkcd.com/1912/", Title: `A title`, Content: `Your problem is so terrible, I worry that, if I help you, I risk drawing the attention of whatever god of technology inflicted it on you.`, } ApplyContentRewriteRules(testEntry, ``) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithXkcdLinkAndNoImage(t *testing.T) { controlEntry := &model.Entry{ URL: "https://xkcd.com/1912/", Title: `A title`, Content: `test`, } testEntry := &model.Entry{ URL: "https://xkcd.com/1912/", Title: `A title`, Content: `test`, } ApplyContentRewriteRules(testEntry, ``) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithXkcdAndNoImage(t *testing.T) { controlEntry := &model.Entry{ URL: "https://xkcd.com/1912/", Title: `A title`, Content: `test`, } testEntry := &model.Entry{ URL: "https://xkcd.com/1912/", Title: `A title`, Content: `test`, } ApplyContentRewriteRules(testEntry, ``) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteMailtoLink(t *testing.T) { controlEntry := &model.Entry{ URL: "https://www.qwantz.com/", Title: `A title`, Content: `contact [blah blah]`, } testEntry := &model.Entry{ URL: "https://www.qwantz.com/", Title: `A title`, Content: `contact`, } ApplyContentRewriteRules(testEntry, ``) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithPDFLink(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/document.pdf", Title: `A title`, Content: `PDF
test`, } testEntry := &model.Entry{ URL: "https://example.org/document.pdf", Title: `A title`, Content: `test`, } ApplyContentRewriteRules(testEntry, ``) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithNoLazyImage(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Image`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Image`, } ApplyContentRewriteRules(testEntry, "add_dynamic_image") if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithLazyImage(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Image`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Image`, } ApplyContentRewriteRules(testEntry, "add_dynamic_image") if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithLazyDivImage(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Image`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
`, } ApplyContentRewriteRules(testEntry, "add_dynamic_image") if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithUnknownLazyNoScriptImage(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `ImageFallback`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Image`, } ApplyContentRewriteRules(testEntry, "add_dynamic_image") if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithLazySrcset(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Image`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Image`, } ApplyContentRewriteRules(testEntry, "add_dynamic_image") if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithImageAndLazySrcset(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Image`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Image`, } ApplyContentRewriteRules(testEntry, "add_dynamic_image") if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithNoLazyIframe(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: ``, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: ``, } ApplyContentRewriteRules(testEntry, "add_dynamic_iframe") if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithLazyIframe(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: ``, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: ``, } ApplyContentRewriteRules(testEntry, "add_dynamic_iframe") if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteWithLazyIframeAndSrc(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: ``, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: ``, } ApplyContentRewriteRules(testEntry, "add_dynamic_iframe") if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestNewLineRewriteRule(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `A
B
C`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: "A\nB\nC", } ApplyContentRewriteRules(testEntry, "nl2br") if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestConvertTextLinkRewriteRule(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Test: http://example.org/a/b`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Test: http://example.org/a/b`, } ApplyContentRewriteRules(testEntry, "convert_text_link") if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestMediumImage(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Image for post`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Image for post
Image for post
`, } ApplyContentRewriteRules(testEntry, "fix_medium_images") testEntry.Content = strings.TrimSpace(testEntry.Content) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteNoScriptImageWithoutNoScriptTag(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
The beautiful MDN logo.
MDN Logo
`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
The beautiful MDN logo.
MDN Logo
`, } ApplyContentRewriteRules(testEntry, "use_noscript_figure_images") testEntry.Content = strings.TrimSpace(testEntry.Content) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteNoScriptImageWithNoScriptTag(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
MDN Logo
`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
The beautiful MDN logo.
MDN Logo
`, } ApplyContentRewriteRules(testEntry, "use_noscript_figure_images") testEntry.Content = strings.TrimSpace(testEntry.Content) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteReplaceCustom(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: ``, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: ``, } ApplyContentRewriteRules(testEntry, `replace("article/(.*).svg"|"article/$1.png")`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteReplaceTitleCustom(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `Ouch, a thistle`, Content: `The replace_title rewrite rule should not modify the content.`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `The replace_title rewrite rule should not modify the content.`, } ApplyContentRewriteRules(testEntry, `replace_title("(?i)^a\\s*ti"|"Ouch, a this")`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteRemoveCustom(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Lorem Ipsum Super important info
`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Lorem Ipsum I dont want to see thisSuper important info
`, } ApplyContentRewriteRules(testEntry, `remove(".spam, .ads:not(.keep)")`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteRemoveQuotedSelector(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Lorem Ipsum
`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Lorem IpsumLINUX KERNEL
`, } ApplyContentRewriteRules(testEntry, `remove("img[src^='/assets/categories/']")`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteAddCastopodEpisode(t *testing.T) { controlEntry := &model.Entry{ URL: "https://podcast.demo/@demo/episodes/test", Title: `A title`, Content: `
Episode Description`, } testEntry := &model.Entry{ URL: "https://podcast.demo/@demo/episodes/test", Title: `A title`, Content: `Episode Description`, } ApplyContentRewriteRules(testEntry, `add_castopod_episode`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteBase64Decode(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `This is some base64 encoded content`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `VGhpcyBpcyBzb21lIGJhc2U2NCBlbmNvZGVkIGNvbnRlbnQ=`, } ApplyContentRewriteRules(testEntry, `base64_decode`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteBase64DecodeInHTML(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Lorem Ipsum not valid base64This is some base64 encoded content
`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Lorem Ipsum not valid base64VGhpcyBpcyBzb21lIGJhc2U2NCBlbmNvZGVkIGNvbnRlbnQ=
`, } ApplyContentRewriteRules(testEntry, `base64_decode`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteBase64DecodeArgs(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Lorem IpsumThis is some base64 encoded content
`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Lorem IpsumVGhpcyBpcyBzb21lIGJhc2U2NCBlbmNvZGVkIGNvbnRlbnQ=
`, } ApplyContentRewriteRules(testEntry, `base64_decode(".base64")`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRewriteRemoveTables(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `

Test

Hello World!

Test

`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `

Test

Hello World!

Test

`, } ApplyContentRewriteRules(testEntry, `remove_tables`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestRemoveClickbait(t *testing.T) { controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `This Is Amazing`, Content: `Some description`, } testEntry := &model.Entry{ URL: "https://example.org/article", Title: `THIS IS AMAZING`, Content: `Some description`, } ApplyContentRewriteRules(testEntry, `remove_clickbait`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestAddHackerNewsLinksUsingHack(t *testing.T) { testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `

Article URL: https://example.org/article

Comments URL: https://news.ycombinator.com/item?id=37620043

Points: 23

# Comments: 38

`, } controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `

Article URL: https://example.org/article

Comments URL: https://news.ycombinator.com/item?id=37620043 Open with HACK

Points: 23

# Comments: 38

`, } ApplyContentRewriteRules(testEntry, `add_hn_links_using_hack`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestAddHackerNewsLinksUsingOpener(t *testing.T) { testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `

Article URL: https://example.org/article

Comments URL: https://news.ycombinator.com/item?id=37620043

Points: 23

# Comments: 38

`, } controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `

Article URL: https://example.org/article

Comments URL: https://news.ycombinator.com/item?id=37620043 Open with Opener

Points: 23

# Comments: 38

`, } ApplyContentRewriteRules(testEntry, `add_hn_links_using_opener`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestAddImageTitle(t *testing.T) { testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: ` "onerror=alert(1) a=" "onerror=alert(1) a=" ;&quot;onerror=alert(1) a=;&quot; pouf pouf pouf `, } controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `

pouf

pouf

pouf

;"onerror=alert(1) a=;"

pouf

pouf

"onerror=alert(1) a="

pouf

"onerror=alert(1) a="

pouf

;&quot;onerror=alert(1) a=;&quot;

`, } ApplyContentRewriteRules(testEntry, `add_image_title`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestFixGhostCard(t *testing.T) { testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Example Article
Lorem ipsum odor amet, consectetuer adipiscing elit. Pretium magnis luctus ligula conubia quam, donec orci vehicula efficitur...
`, } controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Example Article - Example`, } ApplyContentRewriteRules(testEntry, `fix_ghost_cards`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestFixGhostCardNoCard(t *testing.T) { testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Example Article - Example`, } controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Example Article - Example`, } ApplyContentRewriteRules(testEntry, `fix_ghost_cards`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestFixGhostCardInvalidCard(t *testing.T) { testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
This card does not have the required fields
`, } controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
This card does not have the required fields
`, } ApplyContentRewriteRules(testEntry, `fix_ghost_cards`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestFixGhostCardMissingAuthor(t *testing.T) { testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Example Article
Lorem ipsum odor amet, consectetuer adipiscing elit. Pretium magnis luctus ligula conubia quam, donec orci vehicula efficitur...
`, } controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Example Article`, } ApplyContentRewriteRules(testEntry, `fix_ghost_cards`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestFixGhostCardDuplicatedAuthor(t *testing.T) { testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Example Article - Example
Lorem ipsum odor amet, consectetuer adipiscing elit. Pretium magnis luctus ligula conubia quam, donec orci vehicula efficitur...
`, } controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Example Article - Example`, } ApplyContentRewriteRules(testEntry, `fix_ghost_cards`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestFixGhostCardMultiple(t *testing.T) { testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Example Article 1 - Example
Lorem ipsum odor amet, consectetuer adipiscing elit. Pretium magnis luctus ligula conubia quam, donec orci vehicula efficitur...
Example Article 2 - Example
Lorem ipsum odor amet, consectetuer adipiscing elit. Pretium magnis luctus ligula conubia quam, donec orci vehicula efficitur...
`, } controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: ``, } ApplyContentRewriteRules(testEntry, `fix_ghost_cards`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } } func TestFixGhostCardMultipleSplit(t *testing.T) { testEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `
Example Article 1 - Example
Lorem ipsum odor amet, consectetuer adipiscing elit. Pretium magnis luctus ligula conubia quam, donec orci vehicula efficitur...

This separates the two cards

Example Article 2 - Example
Lorem ipsum odor amet, consectetuer adipiscing elit. Pretium magnis luctus ligula conubia quam, donec orci vehicula efficitur...
`, } controlEntry := &model.Entry{ URL: "https://example.org/article", Title: `A title`, Content: `Example Article 1 - Example

This separates the two cards

Example Article 2 - Example`, } ApplyContentRewriteRules(testEntry, `fix_ghost_cards`) if !reflect.DeepEqual(testEntry, controlEntry) { t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry) } }