Repository: raviqqe/muffet
Pull request #542 (2025-07-02 02:33:37)

Refactor network error ignorance

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/raviqqe/muffet/pull/542?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Yota+Toyama) Report
Attention: Patch coverage is `57.14286%` with `6 lines` in your changes missing coverage. Please review.
> Project coverage is 86.43%. Comparing base [(`d043233`)](https://app.codecov.io/gh/raviqqe/muffet/commit/d04323338087dbf72253b008d275b6151b0031a7?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Yota+Toyama) to head [(`dafe8bd`)](https://app.codecov.io/gh/raviqqe/muffet/commit/dafe8bdd6d939787928e43b4d4ddb3765c354eb6?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Yota+Toyama).

| [Files with missing lines](https://app.codecov.io/gh/raviqqe/muffet/pull/542?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Yota+Toyama) | Patch % | Lines |
|---|---|---|
| [command.go](https://app.codecov.io/gh/raviqqe/muffet/pull/542?src=pr&el=tree&filepath=command.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Yota+Toyama#diff-Y29tbWFuZC5nbw==) | 45.45% | [6 Missing :warning: ](https://app.codecov.io/gh/raviqqe/muffet/pull/542?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Yota+Toyama) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main     #542      +/-   ##
==========================================
- Coverage   86.91%   86.43%   -0.49%     
==========================================
  Files          33       33              
  Lines         948      958      +10     
==========================================
+ Hits          824      828       +4     
- Misses         98      104       +6     
  Partials       26       26              
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/raviqqe/muffet/pull/542?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Yota+Toyama).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Yota+Toyama).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>

Patch:
diff --git a/arguments.go b/arguments.go
index 308d4d7..487a513 100644
--- a/arguments.go
+++ b/arguments.go
@@ -22,10 +22,10 @@ type arguments struct {
 	FollowSitemapXML       bool     `long:"follow-sitemap-xml" description:"Scrape only pages listed in sitemap.xml (deprecated)"`
 	RawHeaders             []string `long:"header" value-name:"<header>..." description:"Custom headers"`
 	// TODO Remove a short option.
-	IgnoreFragments     bool                `short:"f" long:"ignore-fragments" description:"Ignore URL fragments"`
-	IgnoreNetworkErrors ignoreNetworkErrors `long:"ignore-network-errors" description:"Ignore network errors and timeouts" choice:"none" choice:"all" choice:"external" default:"none"`
-	DnsResolver         string              `long:"dns-resolver" value-name:"<address>" description:"Custom DNS resolver"`
-	Format              string              `long:"format" description:"Output format" default:"text" choice:"text" choice:"json" choice:"junit"`
+	IgnoreFragments     bool   `short:"f" long:"ignore-fragments" description:"Ignore URL fragments"`
+	IgnoreNetworkErrors string `long:"ignore-network-errors" description:"Ignore network errors and timeouts" choice:"none" choice:"all" choice:"external" default:"none"`
+	DnsResolver         string `long:"dns-resolver" value-name:"<address>" description:"Custom DNS resolver"`
+	Format              string `long:"format" description:"Output format" default:"text" choice:"text" choice:"json" choice:"junit"`
 	// TODO Remove this option.
 	JSONOutput bool `long:"json" description:"Output results in JSON (deprecated)"`
 	// TODO Remove this option.
diff --git a/command.go b/command.go
index a9bf5b7..05b90b5 100644
--- a/command.go
+++ b/command.go
@@ -108,11 +108,23 @@ func (c *command) runWithError(ss []string) (bool, error) {
 		}
 	}
 
+	g := networkErrorGroupNone
+
+	switch args.IgnoreNetworkErrors {
+	case "none":
+	case "all":
+		g = networkErrorGroupAll
+	case "external":
+		g = networkErrorGroupExternal
+	default:
+		return false, fmt.Errorf("invalid network error: %v", args.IgnoreNetworkErrors)
+	}
+
 	checker := newPageChecker(
 		f,
 		newLinkValidator(p.URL().Hostname(), rd, sm),
 		args.OnePageOnly,
-		args.IgnoreNetworkErrors,
+		g,
 	)
 
 	go checker.Check(p)
diff --git a/ignore_network_errors.go b/ignore_network_errors.go
deleted file mode 100644
index f547462..0000000
--- a/ignore_network_errors.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package main
-
-type ignoreNetworkErrors string
-
-const (
-	ignoreNetworkErrorsNone     ignoreNetworkErrors = "none"
-	ignoreNetworkErrorsAll      ignoreNetworkErrors = "all"
-	ignoreNetworkErrorsExternal ignoreNetworkErrors = "external"
-)
diff --git a/network_error.go b/network_error.go
new file mode 100644
index 0000000..b5792b8
--- /dev/null
+++ b/network_error.go
@@ -0,0 +1,9 @@
+package main
+
+type networkErrorGroup int
+
+const (
+	networkErrorGroupNone networkErrorGroup = iota
+	networkErrorGroupAll
+	networkErrorGroupExternal
+)
diff --git a/page_checker.go b/page_checker.go
index 9a1f94e..0143208 100644
--- a/page_checker.go
+++ b/page_checker.go
@@ -15,10 +15,10 @@ type pageChecker struct {
 	results             chan *pageResult
 	donePages           concurrentStringSet
 	onePageOnly         bool
-	ignoreNetworkErrors ignoreNetworkErrors
+	ignoreNetworkErrors networkErrorGroup
 }
 
-func newPageChecker(f *linkFetcher, v *linkValidator, onePageOnly bool, ignore ignoreNetworkErrors) *pageChecker {
+func newPageChecker(f *linkFetcher, v *linkValidator, onePageOnly bool, ignore networkErrorGroup) *pageChecker {
 	return &pageChecker{
 		f,
 		v,
@@ -100,24 +100,14 @@ func (c *pageChecker) addPage(p page) {
 }
 
 func (c *pageChecker) shouldIgnoreNetworkError(err error, rawURL string) bool {
-	if c.ignoreNetworkErrors == ignoreNetworkErrorsNone {
+	if c.ignoreNetworkErrors == networkErrorGroupNone || !isNetworkError(err) {
 		return false
 	}
 
-	if !isNetworkError(err) {
-		return false
-	}
-
-	if c.ignoreNetworkErrors == ignoreNetworkErrorsAll {
-		return true
-	}
-
-	u, parseErr := url.Parse(rawURL)
-	if parseErr != nil {
-		return false
-	}
-
-	return u.Hostname() != c.linkValidator.hostname
+	u, err := url.Parse(rawURL)
+	return err == nil &&
+		(c.ignoreNetworkErrors == networkErrorGroupAll ||
+			u.Hostname() != c.linkValidator.hostname)
 }
 
 func isNetworkError(err error) bool {


Test patch:
diff --git a/page_checker_test.go b/page_checker_test.go
index e39d3b4..c4e0c07 100644
--- a/page_checker_test.go
+++ b/page_checker_test.go
@@ -9,10 +9,10 @@ import (
 )
 
 func newTestPageChecker(c *fakeHttpClient) *pageChecker {
-	return newTestPageCheckerWithIgnore(c, ignoreNetworkErrorsNone)
+	return newTestPageCheckerWithIgnore(c, networkErrorGroupNone)
 }
 
-func newTestPageCheckerWithIgnore(c *fakeHttpClient, ignore ignoreNetworkErrors) *pageChecker {
+func newTestPageCheckerWithIgnore(c *fakeHttpClient, ignore networkErrorGroup) *pageChecker {
 	return newPageChecker(
 		newLinkFetcher(
 			c,
@@ -124,7 +124,7 @@ func TestPageCheckerDoNotCheckSamePageTwice(t *testing.T) {
 	assert.Equal(t, 1, i)
 }
 
-func TestPageCheckerIgnoreNetworkErrorsAll(t *testing.T) {
+func TestPageCheckerIgnoreAllNetworkErrors(t *testing.T) {
 	c := newTestPageCheckerWithIgnore(
 		newFakeHttpClient(
 			func(u *url.URL) (*fakeHttpResponse, error) {
@@ -138,7 +138,7 @@ func TestPageCheckerIgnoreNetworkErrorsAll(t *testing.T) {
 				return nil, fakeNetError{}
 			},
 		),
-		ignoreNetworkErrorsAll,
+		networkErrorGroupAll,
 	)
 
 	go c.Check(newTestPage(t, nil, map[string]error{"http://bar.com": nil}))
@@ -148,12 +148,12 @@ func TestPageCheckerIgnoreNetworkErrorsAll(t *testing.T) {
 	assert.Equal(t, 0, len(r.ErrorLinkResults))
 }
 
-func TestPageCheckerIgnoreNetworkErrorsExternal(t *testing.T) {
+func TestPageCheckerIgnoreExternalNetworkError(t *testing.T) {
 	c := newTestPageCheckerWithIgnore(
 		newFakeHttpClient(func(u *url.URL) (*fakeHttpResponse, error) {
 			return nil, fakeNetError{}
 		}),
-		ignoreNetworkErrorsExternal,
+		networkErrorGroupExternal,
 	)
 
 	go c.Check(newTestPage(t, nil, map[string]error{"http://bar.com": nil}))
@@ -163,12 +163,12 @@ func TestPageCheckerIgnoreNetworkErrorsExternal(t *testing.T) {
 	assert.Equal(t, 0, len(r.ErrorLinkResults))
 }
 
-func TestPageCheckerDoNotIgnoreInternalNetworkErrors(t *testing.T) {
+func TestPageCheckerDoNotIgnoreInternalNetworkError(t *testing.T) {
 	c := newTestPageCheckerWithIgnore(
 		newFakeHttpClient(func(u *url.URL) (*fakeHttpResponse, error) {
 			return nil, fakeNetError{}
 		}),
-		ignoreNetworkErrorsExternal,
+		networkErrorGroupExternal,
 	)
 
 	go c.Check(newTestPage(t, nil, map[string]error{"http://foo.com/foo": nil}))